如果您的features
数组相当接近您的JSON struct 的"顶部"(即只向下一层),那么您可以合理地使用serde来做到这一点.
可悲的是,通常的#[derive(Deserialize)]
机制通常不能在JSON struct 的外层使用,因为您通常需要某种状态来处理特性流,但派生的反序列化程序是无状态的.所以你必须实现两个DeserializeSeed
.
第一个替换了外层 struct 上的#[derive(Deserialize)]
,但在features
上调用next_value_seed
而不是next_value
.这些都是样板文件,我还在等待有人将其添加到serde的派生宏中:
struct FeatureCollectionStream<F>(F);
impl<'de, F: FnMut(Feature)> DeserializeSeed<'de> for FeatureCollectionStream<F> {
type Value = ();
fn deserialize<D>(self, d: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
return d.deserialize_struct("FeatureCollection", &["type", "features"], FCV(self.0));
struct FCV<F>(F);
impl<'de, F: FnMut(Feature)> Visitor<'de> for FCV<F> {
type Value = ();
fn visit_map<A: MapAccess<'de>>(mut self, mut map: A) -> Result<Self::Value, A::Error> {
while let Some(k) = map.next_key::<String>()? {
match k.as_str() {
"type" => {
map.next_value::<String>()?;
}
"features" => map.next_value_seed(FeatureStream(&mut self.0))?,
s => return Err(todo!()),
}
}
Ok(())
}
}
}
}
下一个序列化程序是您实际需要的,它将Feature
的序列作为流处理:
struct FeatureStream<F>(F);
impl<'de, F: FnMut(Feature)> DeserializeSeed<'de> for FeatureStream<F> {
type Value = ();
fn deserialize<D>(self, d: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
return d.deserialize_seq(FV(self.0));
struct FV<F>(F);
impl<'de, F: FnMut(Feature)> Visitor<'de> for FV<F> {
type Value = ();
fn visit_seq<A: serde::de::SeqAccess<'de>>(
mut self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
while let Some(f) = seq.next_element()? {
(self.0)(f)
}
Ok(())
}
}
}
}
可爱的是,你仍然可以对内部 struct 使用派生魔法.
#[derive(Deserialize, Default)]
#[serde(rename_all = "snake_case")]
enum FeatureType {
#[default]
Feature,
}
#[derive(Deserialize, Default)]
struct Feature {
#[allow(unused)]
r#type: FeatureType,
// ...
}
使用这个混合物:
FeatureCollectionStream(|f: Feature| todo!("Do something with each feature"))
.deserialize(&mut serde_json::Deserializer::from_reader(x))?;
带有遗漏错误处理的Playground
(C.F.另有answer by me人采用同样的"伎俩")