Is there a way to omit wrapper/root objects when deserializing objects with Serde?

自古美人都是妖i 提交于 2019-12-06 15:33:56
dtolnay

I would implement this using a wrapper struct that can be used directly for dropping the top level of nesting as well as through a #[serde(with = "...")] attribute for eliminating levels of nesting within the deserialized data structure.


use serde::{Deserialize, Deserializer};

#[derive(Deserialize, Debug)]
struct Continent {
    id: u64,
    name: String,
    #[serde(with = "Wrapper")]
    countries: Vec<Country>,
}

#[derive(Deserialize, Debug)]
struct Country {
    id: u64,
    name: String,
    capital: String,
}

#[derive(Deserialize)]
struct Wrapper<T> {
    data: T,
}

impl<T> Wrapper<T> {
    fn deserialize<'de, D>(deserializer: D) -> Result<T, D::Error>
    where
        T: Deserialize<'de>,
        D: Deserializer<'de>,
    {
        let wrapper = <Self as Deserialize>::deserialize(deserializer)?;
        Ok(wrapper.data)
    }
}

fn main() -> serde_json::Result<()> {
    let j = r#"
        {
          "data": {
            "id": 1,
            "name": "South America",
            "countries": {
              "data": [
                {
                  "id": 122,
                  "name": "Brazil",
                  "capital": "Brasilia"
                }
              ]
            }
          }
        }"#;

    let wrapper: Wrapper<Continent> = serde_json::from_str(j)?;
    println!("{:#?}", wrapper.data);

    Ok(())
}

There are three materially different places where insignificant nesting arises:

  1. adjacent to other fields
  2. by itself at the top level
  3. by itself below the top level

All three require different approaches. #2 and #3 are observed in this question.

To solve #1, see Is it possible to flatten sub-object fields while parsing with serde_json?

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!