Serde десериализация частичных структур с actix_web - PullRequest
0 голосов
/ 28 марта 2020

У меня есть конечная точка 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 сможет десериализовать все поля структуры. Т.е. запрос должен содержать ключи field1 и field2.

Например, это может быть успешно выполнено:

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, которая ожидает присутствия всех полей?

Или, скорее, есть общий c способ десериализации такие частичные структуры с actix_web или serde?

1 Ответ

3 голосов
/ 28 марта 2020

Вы можете использовать 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,
}
...