我有一个结构:
struct S {
data: i32,
fun: Box<Fn()>,
}
并希望使用编码器序列化数据部分。为此,我使用rustc_serialize并派生其特征,如
#[derive(RustcEncodable, RustcDecodable)]
struct S {
data: i32,
fun: Box<Fn()>,
}
问题是fun
无法序列化,因为它是一个功能。这很好,因为我只想序列化普通的data
字段。有没有办法做到这一点?
我的实际用例中的data
字段也是一个结构,它也可以有一个Fn
所以我不能简单地将结构分成两个。
答案 0 :(得分:3)
简短的回答是“不”。 rustc-serialize crate 1 对Decodable
或Encodable
等特征的自动实现没有提供这种控制水平。
为此,您需要自己实施:
extern crate rustc_serialize;
use rustc_serialize::{Encodable, Encoder};
use rustc_serialize::json;
struct S {
data: i32,
fun: Box<Fn()>,
}
impl Encodable for S {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_struct("S", 1, |s| {
s.emit_struct_field("data", 0, |s| {
s.emit_i32(self.data)
})
})
}
}
fn main() {
let thing = S { data: 42, fun: Box::new(|| println!("I am a function")) };
let json = json::encode(&thing).expect("Couldn't encode");
println!("{}", json);
(thing.fun)();
}
如果您不依赖于rustc-serialize,您可能会对提供#[serde(skip_serializing)]
和#[serde(skip_deserializing)]
注释的serde感兴趣。
1 :从技术上讲,编译器提供了#[derive(RustcEncodable, RustcDecodable)]
。这就是它具有Rustc
前缀的原因。它也是一个丑陋的疣,想要被删除,但正在等待编译器插件的稳定支持。
答案 1 :(得分:3)
Shepmaster's answer给出了RustcEncodable解决方案。为了完整起见,这里是等效的Serde代码:
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde_json;
#[derive(Serialize, Deserialize)]
struct S {
data: i32,
#[serde(skip_serializing, skip_deserializing, default="empty_fun")]
fun: Box<Fn()>,
}
fn empty_fun() -> Box<Fn()> {
Box::new(|| {})
}
fn main() {
let s = S { data: 42, fun: Box::new(|| println!("I am a function")) };
// prints {"data":42}
println!("{}", serde_json::to_string(&s).unwrap());
}
skip_serializing
属性表示在序列化结构时忽略该字段。同样,skip_deserializing
属性意味着在反序列化时忽略该字段。
default
属性给出反序列化时用于字段的值。实施std::default::Default
的字段不需要此字段,因为Serde可以使用Default::default()
的值。