【问题标题】:Formatting a struct field differently than its JSON key格式化结构字段与其 JSON 键不同
【发布时间】:2015-05-01 03:19:41
【问题描述】:

Rust 的 rustc-serialize 包允许在某些情况下通过分别从 RustcEncodableRustcDecodable 派生来自动将结构序列化或反序列化为 JSON。例如下面的结构体:

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

将被表示为这个 JSON:

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

我需要反序列化一些使用驼峰式密钥的 JSON。这似乎要求结构字段以类似的方式命名,这会发出编译器警告结构字段应该是蛇形大小写的。我可以用#[allow(non_snake_case)] 使这个警告静音,但我宁愿让结构字段蛇形。有没有办法在不使用 ToJson/Encodable/Decodable 特征手动实现 JSON 序列化/反序列化的情况下做到这一点?

【问题讨论】:

  • 你也可以使用serde,它允许rename fields natively
  • 啊哈!我看着 serde 但不知道它可以做到这一点!文档可能需要一些爱。

标签: rust


【解决方案1】:

不,#[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))
        })
    }
}

【讨论】:

    猜你喜欢
    • 2021-04-23
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多