2016-09-08 14 views
8

シリアル化する前にフィールドに変換を適用するにはどうすればよいですか?Serdeを使用してシリアル化中にフィールドを変換する方法は?

たとえば、この構造体定義内のlatフィールドとlonフィールドを直列化する前に小数点以下6桁まで四捨五入して指定するにはどうすればよいですか?

#[derive(Debug, Serialize)] 
struct NodeLocation { 
    #[serde(rename = "nodeId")] 
    id: u32, 
    lat: f32, 
    lon: f32, 
} 
+1

手動 'Serialize'を実装しますか? – Kroltan

答えて

7

あなたのフィールドにa custom serialization functionを提供するために、serialize_with attributeを使用することができます。

#[macro_use] 
extern crate serde_derive; 

extern crate serde; 
use serde::Serializer; 

fn round_serialize<S>(x: &f32, s: S) -> Result<S::Ok, S::Error> 
where 
    S: Serializer, 
{ 
    s.serialize_f32(x.round()) 
} 

#[derive(Debug, Serialize)] 
pub struct NodeLocation { 
    #[serde(rename = "nodeId")] 
    id: u32, 
    #[serde(serialize_with = "round_serialize")] 
    lat: f32, 
    #[serde(serialize_with = "round_serialize")] 
    lon: f32, 
} 

(私はkにフロートを丸くするための最良の方法は何か」のトピックを避けるために、最も近い整数に丸めました小数位")。

他の半手動アプローチは自動由来のシリアライズと別の構造体を作成し、それを使用してシリアル化を実装することです:

impl Serialize for NodeLocation { 
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> 
    where 
     S: Serializer, 
    { 
     // Implement your preprocessing in `from`. 
     RoundedNodeLocation::from(loc).serialize(s) 
    } 
} 
関連する問題