Macro serde_utils::serde_impl
[−]
[src]
macro_rules! serde_impl { ( $name:ident($ktype:ident?) { $( $fname:ident : $ftype:ty => $fkey:expr ),+ } ) => { ... }; ( $name:ident($ktype:ident) { $( $fname:ident : $ftype:ty => $fkey:expr ),+ } ) => { ... }; ( $name:ident { $( $fname:ident : $ftype:ty ),+ } ) => { ... }; ( $name:ident($ktype:ident) { $( $variant:ident => $fkey:expr ),+ } ) => { ... }; ( $name:ident($ktype:ident) { $( $variant:ident($ftype:ty) => $fkey:expr ),* } ) => { ... }; }
Macro for implementing (de-)serialization via serde in common cases
Using the macro
The macro provides implementations for Serialize and Deserialize for various kinds or
data types. The macro syntax tries to stay as close as possible to the declaration of the
data type.
To use the macro, serde must be imported by either use serde; or extern crate serde;.
(De-)Serializing structs as maps
To deserialize a struct data type as a map, it must implement the Default trait so that
missing struct fields still have a value. The macro syntax for this case is:
serde_impl!($name($ktype) { $fname: $ftype => $fkey, ... });
where
$nameis the name of the type to be implemented.$ktypeis the type for the keys in the mapping.$fnameis the name of a field (on the struct in Rust).$ftypeis the type of a field.$fkeyis the field key in the map (in serialized form).
Example
#[derive(Default)] struct Test { test: String, num: u64, option: Option<bool>, } serde_impl!(Test(String) { test: String => "test", num: u64 => "num", option: Option<bool> => "option" });
Note that the $ktype must be an owned type corresponding to the used field keys,
i.e. String instead of &str in this example.
It is also possible to use numeric field keys (when the serialization supports it, JSON does not).
Example
#[derive(Default)] struct Test { test: String, num: u64, option: Option<bool>, } serde_impl!(Test(u64) { test: String => 0, num: u64 => 1, option: Option<bool> => 2 });
When deserializing data, the generated implementation will silently ignore all extra fields and use the default value for all missing fields.
Compressed maps
By adding a question mark after the key type the serialization will make sure to omit map entries containing the default value. During serialization, the default value will be set on all omitted fields.
serde_impl!(Test(String?) { test: String => "test", num: u64 => "num", option: Option<bool> => "option" });
(De-)Serializing structs as tuples
It is also possible to (de-)serialize structs as tuples containing all the fields in order. The macro syntax for this case is:
serde_impl!($name { $fname: $ftype, ... });
where
$nameis the name of the type to be implemented.$fnameis the name of a field (on the struct in Rust).$ftypeis the type of a field.
Example
struct Test { test: String, num: u64, option: Option<bool>, } serde_impl!(Test { test: String, num: u64, option: Option<bool> });
The syntax basically just omits the key type and the field keys as no keys are used.
The fields will just be (de-)serialized in order as a tuple.
When derserializing a tuple as such a data struct, any missing or extra fields will be treated
as an error. Therefore, the struct does not need to implement Default.
(De-)Serializing simple enumss
(De-)serializing enums that do not have parameters, just maps the variants to and from a serializable data type. The syntax in this case is:
serde_impl!($name($ktype) { $variant => $fkey, ... });
where
$nameis the name of the type to be implemented.$ktypeis the type for the serialized enum variants.$variantis the name of a variant (on the enum in Rust).$fkeyis the key for a variant in serialized from.
Example
enum Test { A, B, C } serde_impl!(Test(String) { A => "a", B => "b", C => "c" });
Note that the $ktype must be an owned type corresponding to the used variant keys,
i.e. String instead of &str in this example.
It is also possible to use numeric variant keys.
Example
enum Test { A, B, C } serde_impl!(Test(u64) { A => 0, B => 1, C => 2 });
(De-)Serializing enumss with one parameter
It is also possible to (de-)serialize enums with exactly one parameter. The syntax in this case is:
serde_impl!($name($ktype) { $variant($ftype) => $fkey, ... });
where
$nameis the name of the type to be implemented.$ktypeis the type for the serialized enum variants.$variantis the name of a variant (on the enum in Rust).$ftypeis the type of the variant parameter.$fkeyis the key for a variant in serialized from.
Example
enum Test { A(u64), B(String), C(bool) } serde_impl!(Test(String) { A(u64) => "a", B(String) => "b", C(bool) => "c" });
Note that the $ktype must be an owned type corresponding to the used variant keys,
i.e. String instead of &str in this example.
It is also possible to use numeric variant keys.
Example
enum Test { A(u64), B(String), C(bool) } serde_impl!(Test(u64) { A(u64) => 0, B(String) => 1, C(bool) => 2 });
The limitation to one parameter can be circumvented by wrapping multiple parameters in a tuple:
enum Test { None(()), Single(String), Multiple((u64, bool)) }
instead of
enum Test { None, Single(String), Multiple(u64, bool) }
Limitations
The following things do not work, and most likely will never work:
- Data types with lifetimes
- Parametrized data types
- Enums with multiple parameters
- Enums where different variants have different parameter counts
- Enums with field names
- Tuple structs
- More fancy key types than String and numeric types might not work