Is it possible to flatten sub-object fields while parsing with serde_json?

谁说我不能喝 提交于 2019-12-17 21:30:42

问题


#[serde(rename)] seems to be the right option, but the documentation does not state if it is possible or how to do it.

This JSON object:

{
   "name" : "myobject"
   "info" : 
   {
      "counter" : "3"
      "foo" : "bar"
   }
}

The corresponding flat Rust struct should be:

#[derive(Deserialize)]
struct Object {
    name: String,
    #[serde(rename="info.counter")] // wrong syntax here !!
    count: i32,
    #[serde(rename="info::foo")] // neither this works
    foo: String,
}

回答1:


There is no built-in way to do this with attributes, but you can write your own Deserialize impl for your Object type that deserializes first to some intermediate helper representation and then rearranges the data into the desired struct.

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

use serde::{Deserialize, Deserializer};

#[derive(Debug)]
struct Object {
    name: String,
    count: i32,
    foo: String,
}

impl<'de> Deserialize<'de> for Object {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        #[derive(Deserialize)]
        struct Outer {
            name: String,
            info: Inner,
        }

        #[derive(Deserialize)]
        struct Inner {
            count: i32,
            foo: String,
        }

        let helper = Outer::deserialize(deserializer)?;
        Ok(Object {
            name: helper.name,
            count: helper.info.count,
            foo: helper.info.foo,
        })
    }
}

fn main() {
    let j = r#"{
                 "name": "myobject",
                 "info": {
                   "count": 3,
                   "foo": "bar"
                 }
               }"#;

    println!("{:#?}", serde_json::from_str::<Object>(j).unwrap());
}

The output is:

Object {
    name: "myobject",
    count: 3,
    foo: "bar"
}

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. #1 is observed in this question.

To solve #2 or #3, see Is there a way to omit wrapper/root objects when deserializing objects with Serde?



来源:https://stackoverflow.com/questions/41042767/is-it-possible-to-flatten-sub-object-fields-while-parsing-with-serde-json

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