如何使用 Serde 在序列化期间转换字段?
Posted
技术标签:
【中文标题】如何使用 Serde 在序列化期间转换字段?【英文标题】:How to transform fields during serialization using Serde? 【发布时间】:2020-03-16 09:55:23 【问题描述】:如何在序列化之前对字段应用转换?
例如,如何确保此结构定义中的字段lat
和lon
在被序列化之前最多四舍五入到小数点后6 位?
#[derive(Debug, Serialize)]
struct NodeLocation
#[serde(rename = "nodeId")]
id: u32,
lat: f32,
lon: f32,
【问题讨论】:
手动实现Serialize
?
【参考方案1】:
serialize_with
属性
您可以使用serialize_with
attribute 为您的领域提供a custom serialization function:
use serde::Serialize, Serializer; // 1.0.104
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 位小数的最佳方法”)。
实现serde::Serialize
另一种半手动的方法是使用自动派生的序列化创建一个单独的结构,并使用它来实现您的序列化:
use serde::Serialize, Serializer; // 1.0.104
#[derive(Debug)]
pub struct NodeLocation
id: u32,
lat: f32,
lon: f32,
impl serde::Serialize for NodeLocation
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
// Implement your preprocessing in `from`.
RoundedNodeLocation::from(self).serialize(s)
#[derive(Debug, Serialize)]
pub struct RoundedNodeLocation
#[serde(rename = "nodeId")]
id: u32,
lat: f32,
lon: f32,
impl<'a> From<&'a NodeLocation> for RoundedNodeLocation
fn from(other: &'a NodeLocation) -> Self
Self
id: other.id,
lat: other.lat.round(),
lon: other.lon.round(),
值得注意的是,这还允许您添加或删除字段,因为“内部”序列化类型基本上可以做任何它想做的事情。
【讨论】:
以上是关于如何使用 Serde 在序列化期间转换字段?的主要内容,如果未能解决你的问题,请参考以下文章