rust - 如何使用 Serde 在序列化期间转换字段?

标签 rust serde

如何在序列化之前对字段应用转换?

例如,如何确保此结构定义中的字段 latlon 在序列化之前四舍五入到最多 6 位小数?

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

最佳答案

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,
}

(我四舍五入到最接近的整数以避免主题“什么是将 float 四舍五入到小数点后 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(),
        }
    }
}

值得注意的是,这还允许您添加或删除字段,因为“内部”序列化类型基本上可以做任何它想做的事情。

关于rust - 如何使用 Serde 在序列化期间转换字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39383809/

相关文章:

Rust Rc<RefCell>::borrow_mut 返回 &mut Rc<RefCell<T>> 而不是 RefMut<T>

rust - 如何使用 Cargo 下载 crate 的文档?

rust - 如何将网站内容下载到字符串中?

rust - 为什么没有为明确实现的类型实现特征?

rust - 如何使用Serde在反序列化期间转换字段?

rust - 是否可以将原始字符串直接反序列化为特定类型?

rust - 如何给多个函数参数相同的类型?

rust - 为什么 `name = *name.trim();` 给我 `expected struct ` std::string::String`, found str`?

rust - 如何使用 serde 重命名 `start` 和 `end` 范围值?

string - 如何在包含 &'static str 的结构上实现 serde::Deserialize?