如何使用 `emit_struct` 和 `emit_struct_field` 序列化自定义结构?
How to use `emit_struct` and `emit_struct_field` to serialize a custom struct?
我已经阅读了 Valve 的 JSON Serialization in Rust, Part 1 并尝试 运行 博文中的代码。最复杂的部分是对自定义结构进行自定义序列化。
我更新了代码片段,因此它可以 运行 在最新的 Rust nightly 上:
extern crate rustc_serialize;
use rustc_serialize::{json, Encodable, Encoder};
struct Person {
name: String,
age: usize,
}
impl Encodable for Person {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
match *self {
Person { name: ref p_name, age: ref p_age, } => {
s.emit_struct("Person", 0, |s| {
try!(s.emit_struct_field( "name", 0, |s| p_name.encode(s)));
try!(s.emit_struct_field( "age", 1, |s| p_age.encode(s)));
try!(s.emit_struct_field( "summary", 2, |s| {
(format!("Nice person named {}, {} years of age", p_name, p_age)).encode(s)
}));
Ok(())
})
},
}
}
}
fn main() {
let person = Person {
name: "John Doe".to_string(),
age: 33,
};
println!("{}" , json::encode(&person).unwrap());
}
上面的输出是{}
,但是正确的结果应该是:
{"age":33,"name":"John Doe","summary":"Nice person named John Doe, 33 years of age"}
我想知道如何使用 Encodable
特性以正确的方式序列化自定义结构。
谢谢。
您的问题出在 emit_struct(..)
调用上。
这个函数的原型是:
fn emit_struct<F>(&mut self, name: &str, len: usize, f: F)
-> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
此处,len
是您的结构的字段数。但是您将其设置为 0
,因此生成的 JSON 字典有 0 个字段。
将其更改为 3 会得到以下输出:
{"name":"John Doe","age":33,"summary":"Nice person named John Doe, 33 years of age"}
看来您的教程已经过时了。它说
We call emit_struct on our encoder and pass it 3 arguments: the name of the struct, current index and an anonymous function(aka lambda). The name of the struct is not used; current index is not used too.
fn emit_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult<()> where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult<()>,
{
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if len == 0 {
try!(write!(self.writer, "{{}}"));
所以参数从 index 变成了 length,现在有意义了。这是您的示例工作:
extern crate rustc_serialize;
use rustc_serialize::{json, Encodable, Encoder};
struct Person {
name: String,
age: usize,
}
impl Encodable for Person {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_struct("Person", 1, |s| {
try!(s.emit_struct_field("name", 0, |s| self.name.encode(s)));
try!(s.emit_struct_field("age", 1, |s| self.age.encode(s)));
try!(s.emit_struct_field("summary", 2, |s| {
let summary = format!("Nice person named {}, {} years of age", self.name, self.age);
summary.encode(s)
}));
Ok(())
})
}
}
fn main() {
let person = Person {
name: "John Doe".to_string(),
age: 33,
};
println!("{}" , json::encode(&person).unwrap());
}
请注意,我还删除了疯狂旋转以解构 self
并直接访问属性。
我已经阅读了 Valve 的 JSON Serialization in Rust, Part 1 并尝试 运行 博文中的代码。最复杂的部分是对自定义结构进行自定义序列化。
我更新了代码片段,因此它可以 运行 在最新的 Rust nightly 上:
extern crate rustc_serialize;
use rustc_serialize::{json, Encodable, Encoder};
struct Person {
name: String,
age: usize,
}
impl Encodable for Person {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
match *self {
Person { name: ref p_name, age: ref p_age, } => {
s.emit_struct("Person", 0, |s| {
try!(s.emit_struct_field( "name", 0, |s| p_name.encode(s)));
try!(s.emit_struct_field( "age", 1, |s| p_age.encode(s)));
try!(s.emit_struct_field( "summary", 2, |s| {
(format!("Nice person named {}, {} years of age", p_name, p_age)).encode(s)
}));
Ok(())
})
},
}
}
}
fn main() {
let person = Person {
name: "John Doe".to_string(),
age: 33,
};
println!("{}" , json::encode(&person).unwrap());
}
上面的输出是{}
,但是正确的结果应该是:
{"age":33,"name":"John Doe","summary":"Nice person named John Doe, 33 years of age"}
我想知道如何使用 Encodable
特性以正确的方式序列化自定义结构。
谢谢。
您的问题出在 emit_struct(..)
调用上。
这个函数的原型是:
fn emit_struct<F>(&mut self, name: &str, len: usize, f: F)
-> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>;
此处,len
是您的结构的字段数。但是您将其设置为 0
,因此生成的 JSON 字典有 0 个字段。
将其更改为 3 会得到以下输出:
{"name":"John Doe","age":33,"summary":"Nice person named John Doe, 33 years of age"}
看来您的教程已经过时了。它说
We call emit_struct on our encoder and pass it 3 arguments: the name of the struct, current index and an anonymous function(aka lambda). The name of the struct is not used; current index is not used too.
fn emit_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult<()> where
F: FnOnce(&mut Encoder<'a>) -> EncodeResult<()>,
{
if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); }
if len == 0 {
try!(write!(self.writer, "{{}}"));
所以参数从 index 变成了 length,现在有意义了。这是您的示例工作:
extern crate rustc_serialize;
use rustc_serialize::{json, Encodable, Encoder};
struct Person {
name: String,
age: usize,
}
impl Encodable for Person {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_struct("Person", 1, |s| {
try!(s.emit_struct_field("name", 0, |s| self.name.encode(s)));
try!(s.emit_struct_field("age", 1, |s| self.age.encode(s)));
try!(s.emit_struct_field("summary", 2, |s| {
let summary = format!("Nice person named {}, {} years of age", self.name, self.age);
summary.encode(s)
}));
Ok(())
})
}
}
fn main() {
let person = Person {
name: "John Doe".to_string(),
age: 33,
};
println!("{}" , json::encode(&person).unwrap());
}
请注意,我还删除了疯狂旋转以解构 self
并直接访问属性。