我必须反序列化JSON blob,在某些地方,整个对象的缺失被编码为具有相同结构的对象,但其所有字段均设置为默认值(空字符串和零)。
extern crate serde_json; // 1.0.27
#[macro_use] extern crate serde_derive; // 1.0.78
extern crate serde; // 1.0.78
#[derive(Debug, Deserialize)]
struct Test<T> {
text: T,
number: i32,
}
#[derive(Debug, Deserialize)]
struct Outer {
test: Option<Test<String>>,
}
#[derive(Debug, Deserialize)]
enum Foo { Bar, Baz }
#[derive(Debug, Deserialize)]
struct Outer2 {
test: Option<Test<Foo>>,
}
fn main() {
println!("{:?}", serde_json::from_str::<Outer>(r#"{ "test": { "text": "abc", "number": 42 } }"#).unwrap());
// good: Outer { test: Some(Test { text: "abc", number: 42 }) }
println!("{:?}", serde_json::from_str::<Outer>(r#"{ "test": null }"#).unwrap());
// good: Outer { test: None }
println!("{:?}", serde_json::from_str::<Outer>(r#"{ "test": { "text": "", "number": 0 } }"#).unwrap());
// bad: Outer { test: Some(Test { text: "", number: 0 }) }
// should be: Outer { test: None }
println!("{:?}", serde_json::from_str::<Outer2>(r#"{ "test": { "text": "Bar", "number": 42 } }"#).unwrap());
// good: Outer2 { test: Some(Test { text: Bar, number: 42 }) }
println!("{:?}", serde_json::from_str::<Outer2>(r#"{ "test": { "text": "", "number": 0 } }"#).unwrap());
// bad: error
// should be: Outer { test: None }
}
我将在反序列化之后处理此问题,但是如您所见,对于枚举值,这种方法是不可能的:没有变量与空字符串匹配,因此反序列化完全失败。
我该如何教他们学习?
答案 0 :(得分:-1)
您可以查看an example of custom field deserializing。
特别是,您可能想要定义类似
extern crate serde; // 1.0.78
#[macro_use]
extern crate serde_derive; // 1.0.78
use serde::{Deserialize, Deserializer, de::Visitor};
fn none_if_all_default<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de> + Clone,
{
struct AllDefault;
impl<'de> Visitor<'de> for AllDefault {
type Value = bool;
// Implement the visitor functions here -
// You can recurse over all values to check if they're
// the empty string or 0, and return true
//...
}
let all_default = deserializer.clone().deserialize_any(AllDefault)?;
if all_default {
Ok(None)
} else {
Ok(Some(T::deserialize(deserializer)?))
}
}
然后做
#[derive(Deserialize)]
struct Outer2 {
#[serde(deserialize_with = "none_if_all_default")]
test: Option<Test<Foo>>,
}