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

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

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

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

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: