首页 > 解决方案 > 使用 actix_web 对部分结构进行 Serde 反序列化

问题描述

我有一个 API 端点,actix_web用于反序列化传入的 JSON 有效负载(actix_web最终serde用于 JSON 反序列化)。

例如,我有一些看起来像这样的东西:

pub struct IncomingPayload {
    pub field1: i32,
    pub field2: String
}

pub async fn update_platforms(
    pool: web::Data<Pool>,
    req: web::Json<Vec<IncomingPayload>>,
) -> Result<HttpResponse, error::Error> { 
    println!(req.field1); // will be an i32
    println!(req.field2); // will be a String
}

serde目前,只有能够反序列化结构的所有字段,此端点才会成功返回。即一个请求必须包含field1field2键。

例如,这将是成功的:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"field1": 1,"field2":"something"}' \
  http://localhost:8080

但这不会(因为field2有效载荷中缺少):

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"field1": 1}' \
  http://localhost:8080

所以我的问题是,这可以做到吗?可以将带有键值字段子集的 JSON 有效负载发送到actix_web期望所有字段都存在的端点吗?

或者更确切地说,是否有一种通用的方法可以用actix_webor反序列化像这样的部分结构serde

标签: jsonrustserderust-actixactix-web

解决方案


您可以将Option<T>其用作字段的类型以使其成为可选。如果反序列化过程中缺少某个字段,则该字段设置为None,否则设置为Some(value)

#[derive(Deserialize)]
struct IncomingPayload {
    pub field1: Option<i32>,
    pub field2: Option<String>,
}

对于实现 的类型,如果字段缺失Default,您还可以使用 将字段设置为默认值。#[serde(default)]

#[derive(Deserialize)]
struct IncomingPayload {
    #[serde(default)] // default = 0
    pub field1: i32,
    #[serde(default)] // default = empty string
    pub field2: String,
}

推荐阅读