2016-05-18 57 views
1

我有这样一个结构:是否可以派生(RustcEncodable)的一部分结构?

struct S { 
    data: i32, 
    fun: Box<Fn()>, 
} 

并想序列化使用编码器的数据部分。要做到这一点我用rustc_serialize并从中获得像

#[derive(RustcEncodable, RustcDecodable)] 
struct S { 
    data: i32, 
    fun: Box<Fn()>, 
} 

的问题其特点是,因为它是一个功能fun不能被序列化。这很好,因为我只想序列化原始的data字段。有没有办法做到这一点?

我的真实用例中的data字段也是一个结构,它也可以有Fn,所以我不能简单地将结构拆分为两个。

回答

2

简短答案是“否”。 rustc序列化板条箱不能提供像DecodableEncodable这样的特征的自动化实现的那种控制级别。

要做到这一点,你需要自己实现这些功能:

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序列化,你可能有兴趣在serde它提供了#[serde(skip_serializing)]#[serde(skip_deserializing)]注解。


:从技术上讲,#[derive(RustcEncodable, RustcDecodable)]是由编译器提供。这就是为什么它有前缀Rustc。这也是一个丑陋的疣,想要被删除,但正在等待编译器插件的稳定支持。

2

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()

相关问题