2016-12-08 12 views
2

#[serde(rename)] представляется правильным вариантом, но в документации не указано, возможно ли это или как это сделать.Возможно ли выравнивание полей под-объекта при разборе с помощью serde_json?

Этот JSON объект:

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

Соответствующая плоская Rust структура должна быть:

#[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

Как примечание, нет * производительности * недостатка, имеющих вложенную-структуру; есть только организация кода, о которой нужно беспокоиться. – Shepmaster

+3

Это еще не возможно: https://github.com/serde-rs/serde/issues/119 –

ответ

1

Там нет встроенного способа сделать это с помощью атрибутов, но вы можете написать собственный Deserialize impl для вашего типа Object, который десериализует сначала некоторое промежуточное вспомогательное представление, а затем перестраивает данные в нужную структуру.

#[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()); 
} 

Выход:

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