Я хочу десериализовать следующую структуру, используя 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
, даже если он не существует.
Вы можете 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);
}
Включение объяснения @kmdreko в ответ значительно улучшит его!
Это довольно забавно, поскольку кажется тавтологичным: при десериализации любого поля для этого будет использоваться его реализация
Type::deserialize
. Но это работает, потому чтоOption<_>
является особым случаем для serde с#[serde(default)]
, потому что он часто предназначен для обработки пропущенных значений. Однако добавлениеdeserialize_with
пропускает этот специальный регистр, и он больше не принимает значение по умолчаниюNone
(и, следовательно, не жалуется при его отсутствии).