2016-12-08 5 views
2

#[serde(rename)]が正しい選択肢だと思われますが、可能であれば文書化はできません。serde_jsonで解析中にサブオブジェクトフィールドを平坦化することはできますか?

このJSONオブジェクトは:

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

対応フラット錆構造体は次のようになります。

#[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" 
} 
関連する問題