【发布时间】:2019-12-19 11:04:46
【问题描述】:
不要将字段定义为可选字段,而是同时收集Nones 和Somes,如下所示:
extern crate serde;
extern crate serde_json;
use serde::Deserialize;
#[derive(Debug, Deserialize, PartialEq)]
struct Bar {
a: u32,
b: Option<u32>,
}
#[derive(Debug, Deserialize, PartialEq)]
struct Foo {
vec: Vec<Bar>,
}
fn main() {
let data = r#"{ "vec": [ { "a": 1 }, { "a": 2, "b": 3 } ] }"#;
assert_eq!(
serde_json::from_str::<Foo>(data).unwrap(),
Foo {
vec: vec![Bar { a: 1, b: None }, Bar { a: 2, b: Some(3) }]
}
);
}
最好只收集完全定义的元素,这样Bar 结构可以定义为struct Bar { a: u32, b: u32 },serde_json::from_str 将简单地返回Foo { vec: [ Bar { a: 2, b: 3 } ] }。
如何实现这样的行为?这是我创建自定义Deserialize 实现以尝试解决此问题的失败尝试。
extern crate serde;
extern crate serde_json;
use core::fmt;
use serde::{
de::{SeqAccess, Visitor},
Deserialize, Deserializer,
};
#[derive(Debug, Deserialize)]
struct Bar {
a: i32,
b: i32,
c: i32,
}
#[derive(Debug)]
struct VecOpt(Vec<Bar>);
impl<'de> Deserialize<'de> for VecOpt {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct ArrayVecVisitor;
impl<'de> Visitor<'de> for ArrayVecVisitor {
type Value = VecOpt;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "VecOpt")
}
fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error>
where
SA: SeqAccess<'de>,
{
let mut values = Vec::new();
loop {
match seq.next_element::<Bar>() {
Ok(Some(x)) => values.push(x),
Ok(None) => break,
// If error, the input reader won't move to the next element of the sequence and the following `seq.next_element` will
// simply try to read contents of the current element. In this case, `"c": 5 }, ... `
Err(_) => {}
}
}
Ok(VecOpt(values))
}
}
deserializer.deserialize_seq(ArrayVecVisitor)
}
}
#[derive(Debug, Deserialize)]
struct Foo {
vec: VecOpt,
}
fn main() {
let data = r#"{ "vec": [ { "a": 1 "b": 2, "c": 3 }, { "b": 4, "c": 5 }, { "a": 6 "b": 7, "c": 8 } ] }"#;
dbg!(serde_json::from_str::<Foo>(data).unwrap());
}
【问题讨论】:
-
您的问题不包含实际问题或说明任何问题。
-
foo.vec.into_iter().filter_map(|b| Some(Baz { a: b.a, b: b.b? })).collect()? -
@hellow 这会进行额外分配,我希望在反序列化时收集数据
-
如果你在做
collect,是的。
标签: rust deserialization serde