Macro serde_with::with_prefix
source · macro_rules! with_prefix { ($module:ident $prefix:expr) => { ... }; ($vis:vis $module:ident $prefix:expr) => { ... }; }
Expand description
Serialize with an added prefix on every field name and deserialize by trimming away the prefix.
You can set the visibility of the generated module by prefixing the module name with a module visibility.
with_prefix!(pub(crate) prefix_foo "foo_");
creates a module with pub(crate)
visibility.
The visibility is optional and by default pub(self)
, i.e., private visibility is assumed.
Note: Use of this macro is incompatible with applying the deny_unknown_fields
attribute
on the container.
While deserializing, it will always warn about unknown fields, even though they are processed
by the with_prefix
wrapper.
More details can be found in this issue.
Example
The Challonge REST API likes to use prefixes to group related fields. In simplified form, their JSON may resemble the following:
{
"player1_name": "name1",
"player1_votes": 1,
"player2_name": "name2",
"player2_votes": 2
}
In Rust, we would ideally like to model this data as a pair of Player
structs, rather than repeating the fields of Player
for each prefix.
struct Match {
player1: Player,
player2: Player,
}
struct Player {
name: String,
votes: u64,
}
This with_prefix!
macro produces an adapter that adds a prefix onto field
names during serialization and trims away the prefix during deserialization.
An implementation of the Challonge API would use with_prefix!
like this:
use serde::{Deserialize, Serialize};
use serde_with::with_prefix;
#[derive(Serialize, Deserialize)]
struct Match {
#[serde(flatten, with = "prefix_player1")]
player1: Player,
#[serde(flatten, with = "prefix_player2")]
player2: Player,
}
#[derive(Serialize, Deserialize)]
struct Player {
name: String,
votes: u64,
}
with_prefix!(prefix_player1 "player1_");
// You can also set the visibility of the generated prefix module, the default is private.
with_prefix!(pub prefix_player2 "player2_");
fn main() {
let m = Match {
player1: Player {
name: "name1".to_owned(),
votes: 1,
},
player2: Player {
name: "name2".to_owned(),
votes: 2,
},
};
let j = serde_json::to_string_pretty(&m).unwrap();
println!("{}", j);
}