Rust Json序列化重叠职责 [英] Rust Json serialization overlapping responsibilities

查看:91
本文介绍了Rust Json序列化重叠职责的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Rust中学习Json序列化,特别是如何将Rust对象序列化为Json.

I'm learning Json serialization in Rust, in particular, how to serialize Rust objects to Json.

目前,我看到3种将结构实例转换为Json的方法:

Currently I see 3 methods of converting an instance of a struct to Json:

  1. 获得可编码特征

  1. Deriving Encodable trait

ToJson特质的手动实现

Manual implementation of ToJson trait

可编码特征的手动实现

下面的代码说明了所有3种方法:

Below code illustrates all 3 approaches:

extern crate serialize;

use serialize::{Encoder, Encodable, json};
use serialize::json::{Json, ToJson};
use std::collections::TreeMap;

fn main() {
  let document = Document::new();
  let word_document = WordDocument::new();
  println!("1. Deriving `Encodable`: {}", json::encode(&document));
  println!("2. Manually implementing `ToJson` trait: {}", document.to_json());
  println!("3. Manually implementing `Encodable` trait: {}", json::encode(&word_document));
}

#[deriving(Encodable)]
struct Document<'a> {
  metadata: Vec<(&'a str, &'a str)>
}

impl<'a> Document<'a> {
  fn new() -> Document<'a> {
    let metadata = vec!(("Title", "Untitled Document 1"));
    Document {metadata: metadata}
  }
}

impl<'a> ToJson for Document<'a> {
  fn to_json(&self) -> Json {
    let mut tm = TreeMap::new();
    for &(ref mk, ref mv) in self.metadata.iter() {
      tm.insert(mk.to_string(), mv.to_string().to_json());
    }
    json::Object(tm)
  }
}

struct WordDocument<'a> {
  metadata: Vec<(&'a str, &'a str)>
}

impl<'a> WordDocument<'a> {
  fn new() -> WordDocument<'a> {
    let metadata = vec!(("Title", "Untitled Word Document 1"));
    WordDocument {metadata: metadata}
  }
}

impl<'a, E, S: Encoder<E>> Encodable<S, E> for WordDocument<'a> {
  fn encode(&self, s: &mut S) -> Result<(), E> {
    s.emit_map(self.metadata.len(), |e| {
      let mut i = 0;
      for &(ref key,  ref val) in self.metadata.iter() {
        try!(e.emit_map_elt_key(i, |e| key.encode(e)));
        try!(e.emit_map_elt_val(i, |e| val.encode(e)));
        i += 1;
      }
      Ok(())
    })
  }
}

锈迹斑斑的围栏: http://is.gd/r7cYmE

结果:

1. Deriving `Encodable`: {"metadata":[["Title","Untitled Document 1"]]}
2. Manually implementing `ToJson` trait: {"Title":"Untitled Document 1"}
3. Manually implementing `Encodable` trait: {"Title":"Untitled Word Document 1"}

第一种方法是全自动的,但是没有提供足够的灵活性. 第二个和第三个通过手动指定序列化过程实现了相同级别的灵活性.就我而言,我希望文档元数据被序列化为一个对象,而不是数组(这是派生实现给我的).

First method is fully automatic, but does not provide sufficient flexibility. Second and third achieve same level of flexibility by specifying the serialization process manually. In my case I want document metadata to be serialized as an object, not as an array (which is what deriving implementation gives me).

问题:

  1. 为什么方法2和方法3都存在?我不了解它们之间重叠的原因.我希望那里仅存在一种自动(派生)序列化方法和一本手册.
  2. 如果要手动序列化,应该选择哪种方法,为什么?

  1. Why do methods 2 and 3 exist at all? I don't understand the reason for the overlap between them. I would expect there to exist only one automatic (deriving) method of serialization and one manual.
  2. If I want manual serialization, which method should I choose and why?

我正确地认为方法2将在内存中建立一个Json枚举(除了结构本身),并且更不适合大型文档(数兆字节),而方法3可以进行流传输并且更安全大文件?

Am I right in assuming that method 2 will build a Json enum in memory (besides the struct itself) and is a worse fit for huge documents (multi megabytes), while method 3 is streaming and safer for huge documents?

为什么rust stdlib即使对于图元也使用方法3,而不在内部使用方法2?

Why does rust stdlib use method 3 even for primitives, while not using method 2 internally?

推荐答案

为什么方法2和方法3都存在?我不了解它们之间重叠的原因.我希望那里仅存在一种自动(派生)序列化方法和一本手册.

Why do methods 2 and 3 exist at all? I don't understand the reason for the overlap between them. I would expect there to exist only one automatic (deriving) method of serialization and one manual.

方法2(ToJson特征)专用于编码JSON.它返回JSON对象,而不是写入流.一个使用示例是映射到自定义表示形式-请参见

Method 2 (the ToJson trait) is specific to encoding JSON. It returns JSON objects, instead of writing to a stream. One example of use is for mapping to custom representations - see this example in the documentation.

方法3(实现Encodable)必须存在,方法1才能起作用.

Method 3 (implementing Encodable) has to exist for method 1 to work.

我是否正确地认为方法2将在内存中构建一个Json枚举(除了结构本身),并且更不适用于大型文档(数兆字节),而方法3对于大型文档则是流式传输且更安全?

Am I right in assuming that method 2 will build a Json enum in memory (besides the struct itself) and is a worse fit for huge documents (multi megabytes), while method 3 is streaming and safer for huge documents?

是的. ToJson创建整个对象的嵌套Json枚举,而Encodable流到Writer.

Yes. ToJson creates a nested Json enum of the whole object, while Encodable streams to a Writer.

如果要手动序列化,应该选择哪种方法,为什么?

If I want manual serialization, which method should I choose and why?

为什么rust stdlib即使对于基元也使用方法3,而不在内部使用方法2?

Why does rust stdlib use method 3 even for primitives, while not using method 2 internally?

您应该使用 Encodable .它不是特定于JSON格式,不使用中间表示(因此可以流式传输而不是存储在内存中),并且应该继续使用添加到库中的新格式.

You should use Encodable. It is not specific to the JSON format, does not use an intermediate representation (so can be streamed instead of stored in memory) and should continue to work with new formats added to the library.

这篇关于Rust Json序列化重叠职责的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆