Требовать, чтобы поле было целым числом или нулевым значением, но не отсутствовало в JSON

Я хочу десериализовать следующую структуру, используя serde_json. Поле parent_id должно принимать целое число или ноль, но я хочу, чтобы оно возвращало ошибку, если поле отсутствует.

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
   pub name: String,
   pub parent_id: Option<i32>,
}

// this is accepted
serde_json::from_value(json!({
   "name": "Group 1",
   "parent_id": null,
});

// this should return an error
serde_json::from_value(json!({
   "name": "Group 1",
});

Я попробовал использовать приведенный выше код, но parent_id будет десериализован в None, даже если он не существует.

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
5
0
146
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете deserialize_with с помощью специальной функции, чтобы получить ожидаемое поведение.

use serde::{Deserialize, Deserializer, Serialize};
use serde_json::json;


#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
   pub name: String,
   #[serde(deserialize_with = "Option::deserialize")]
   pub parent_id: Option<i32>,
}

fn main() {
    // thread 'main' panicked at src/main.rs:25:10:
    // called `Result::unwrap()` on an `Err` value: Error("missing field 
    // `parent_id`", line: 0, column: 0)
    let r: Group = serde_json::from_value(json!({
        "name": "Group 1",
     })).unwrap();
    println!("{:?}", r);

}

Это довольно забавно, поскольку кажется тавтологичным: при десериализации любого поля для этого будет использоваться его реализация Type::deserialize. Но это работает, потому что Option<_> является особым случаем для serde с #[serde(default)], потому что он часто предназначен для обработки пропущенных значений. Однако добавление deserialize_with пропускает этот специальный регистр, и он больше не принимает значение по умолчанию None (и, следовательно, не жалуется при его отсутствии).

kmdreko 09.07.2024 17:29

Включение объяснения @kmdreko в ответ значительно улучшит его!

user4815162342 09.07.2024 19:40

Другие вопросы по теме