32

How can I apply a transformation to a field before serialization?

For example, how can I ensure that the fields lat and lon in this struct definition are rounded to at most 6 decimal places before being serialized?

#[derive(Debug, Serialize)] struct NodeLocation { #[serde(rename = "nodeId")] id: u32, lat: f32, lon: f32, } 
1
  • 1
    Manually implement Serialize? Commented Sep 8, 2016 at 10:55

1 Answer 1

53

The serialize_with attribute

You can use the serialize_with attribute to provide a custom serialization function for your field:

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

(I've rounded to the nearest integer to avoid the topic "what is best way to round a float to k decimal places").

Implement serde::Serialize

The other semi-manual approach is to create a separate struct with auto-derived serialization, and implement your serialization using that:

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

Notably, this allows you to also add or remove fields as the "inner" serialized type can do basically whatever it wants.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.