2015-05-01 65 views
3

Rust的rustc-serialize包允許結構分別從RustcEncodableRustcDecodable中分別自動序列化或反序列化爲JSON。例如,下面的結構:格式化結構字段的方式與其JSON密鑰的格式不同

#[derive(RustcEncodable, RustcDecodable)] 
struct Person { 
    first_name: String, 
    last_name: String, 
    age: u8, 
} 

將表示爲這個JSON:

{ 
    "first_name": "Joe", 
    "last_name": "Shmoe", 
    "age": 30 
} 

我需要反序列化使用了駝峯式大小寫鍵一些JSON。這似乎要求struct字段的命名方式相似,這會發出編譯器警告,結構字段應該是蛇形的。我可以用#[allow(non_snake_case)]來消除這個警告,但我寧願讓struct字段是蛇形的。有沒有辦法做到這一點,而不用手動實現JSON序列化/反序列化與ToJson/Encodable/Decodable特徵?

+0

您也可以使用[serde](https://github.com/erickt/rust-serde),它允許[原生重命名字段](https://github.com/Byron/google-apis -rs /斑點/ c2dd9c7a020e0367bc87b20fa8054c85f48b71c1 /根/ adexchangebuyer1d3/SRC/lib.rs#L416)。 – Byron

+0

啊哈!我看着serde,但不知道它可以做到這一點!文檔可能需要一些愛。 –

回答

4

不,#[derive]基礎設施根本沒有提供任何定製機會。

你可以,但是,知道#[derive]東西擴展做什麼用rustc -Z unstable-options --pretty expanded

#![feature(no_std)] 
#![no_std] 
#[prelude_import] 
use std::prelude::v1::*; 
#[macro_use] 
extern crate std as std; 
struct Person { 
    first_name: String, 
    last_name: String, 
    age: u8, 
} 
#[automatically_derived] 
impl ::rustc_serialize::Decodable for Person { 
    fn decode<__D: ::rustc_serialize::Decoder>(__arg_0: &mut __D) 
    -> ::std::result::Result<Person, __D::Error> { 
     __arg_0.read_struct("Person", 3usize, |_d| -> _ { 
          ::std::result::Result::Ok(Person{first_name: 
                   match _d.read_struct_field("first_name", 
                          0usize, 
                          ::rustc_serialize::Decodable::decode) 
                    { 
                    ::std::result::Result::Ok(__try_var) 
                    => 
                    __try_var, 
                    ::std::result::Result::Err(__try_var) 
                    => 
                    return ::std::result::Result::Err(__try_var), 
                   }, 
                  last_name: 
                   match _d.read_struct_field("last_name", 
                          1usize, 
                          ::rustc_serialize::Decodable::decode) 
                    { 
                    ::std::result::Result::Ok(__try_var) 
                    => 
                    __try_var, 
                    ::std::result::Result::Err(__try_var) 
                    => 
                    return ::std::result::Result::Err(__try_var), 
                   }, 
                  age: 
                   match _d.read_struct_field("age", 
                          2usize, 
                          ::rustc_serialize::Decodable::decode) 
                    { 
                    ::std::result::Result::Ok(__try_var) 
                    => 
                    __try_var, 
                    ::std::result::Result::Err(__try_var) 
                    => 
                    return ::std::result::Result::Err(__try_var), 
                   },}) }) 
    } 
} 
#[automatically_derived] 
impl ::rustc_serialize::Encodable for Person { 
    fn encode<__S: ::rustc_serialize::Encoder>(&self, __arg_0: &mut __S) 
    -> ::std::result::Result<(), __S::Error> { 
     match *self { 
      Person { 
      first_name: ref __self_0_0, 
      last_name: ref __self_0_1, 
      age: ref __self_0_2 } => 
      __arg_0.emit_struct("Person", 3usize, |_e| -> _ { 
           match _e.emit_struct_field("first_name", 
                  0usize, |_e| -> _ { 
                  (*__self_0_0).encode(_e) 
                 }) { 
            ::std::result::Result::Ok(__try_var) => 
            __try_var, 
            ::std::result::Result::Err(__try_var) => 
            return ::std::result::Result::Err(__try_var), 
           }; 
           match _e.emit_struct_field("last_name", 
                  1usize, |_e| -> _ { 
                  (*__self_0_1).encode(_e) 
                 }) { 
            ::std::result::Result::Ok(__try_var) => 
            __try_var, 
            ::std::result::Result::Err(__try_var) => 
            return ::std::result::Result::Err(__try_var), 
           }; 
           return _e.emit_struct_field("age", 2usize, 
                  |_e| -> _ { 
                  (*__self_0_2).encode(_e) 
                 }); }), 
     } 
    } 
} 

是啊,這是相當笨拙,所有展開這樣的,但它可以很容易地摺疊和改變,以適應:

impl Decodable for Person { 
    fn decode<D: Decoder>(decoder: &mut D) -> Result<Person, D::Error> { 
     decoder.read_struct("Person", 3, |d| Ok(Person { 
      first_name: try!(d.read_struct_field("firstName", 0, Decodable::decode)), 
      last_name: try!(d.read_struct_field("lastName", 1, Decodable::decode)), 
      age: try!(d.read_struct_field("age", 2, Decodable::decode)), 
     })) 
    } 
} 

impl Encodable for Person { 
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { 
     s.emit_struct("Person", 3, |e| { 
      try!(e.emit_struct_field("firstName", 0, |e| self.first_name.encode(e))); 
      try!(e.emit_struct_field("lastName", 1, |e| self.last_name.encode(e))); 
      e.emit_struct_field("age", 2, |e| self.age.encode(e)) 
     }) 
    } 
}