2016-05-18 77 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()

相關問題