Derive Macro jomini::JominiDeserialize

source ·
#[derive(JominiDeserialize)]
{
    // Attributes available to this derive:
    #[jomini]
}
Expand description

Creates a serde compatible Deserialize implementation

use jomini_derive::JominiDeserialize;

#[derive(JominiDeserialize)]
pub struct Model {
    #[jomini(default = "default_true")]
    human: bool,
    first: Option<u16>,
    #[jomini(alias = "forth")]
    fourth: u16,
    #[jomini(alias = "core", duplicated)]
    cores: Vec<String>,
    names: Vec<String>,
}

fn default_true() -> bool {
    true
}

§The What

Most rust programmers should be already familiar with serde’s Deserialize derive macro. If not, read the serde docs.

The JominiDeserialize macro produces an implementation for the serde Deserialize trait.

When unadored with field attributes, both JominiDeserialize and Deserialize would produce extremely similar Deserialize implementations. It’s a goal for JominiDeserialize to be as compatible as possible.

The value add for JominiDeserialize is the #[jomini(duplicated)] field attribute, which can decorate a Vec<T> field. The duplicated attribute will allow multiple instances of the field, no matter how far separated they are in the data, to be aggregated into a single vector. See “The Why” section below for further info.

In addition to the duplicated attribute, several of the most common serde attributes have been implemented:

  • #[jomini(alias = "abc")]
  • #[jomini(default)]
  • #[jomini(default = "...")]
  • #[jomini(deserialize_with = "...")]

Another attribute unique to jomini is #[jomini(take_last)] which will take the last occurence of a field. Helpful when a field is duplicated accidentally.

§The Why

Serde’s Deserialize implementation will raise an error if a field occurs more than once in the data like shown below:

{
   "core": "core1",
   "nums": [1, 2, 3, 4, 5],
   "core": "core2"
}

The core field occurs twice in the JSON and serde will be unable to aggregate that into a Vec<String> by itself. See this serde issue for more information.

Initial implementations that used the Deserialize derive macro natively required a translation layer that would present the aggregated fields to serde. This translation layer could have a heavy cost especially as documents increased in size.

Thus the need was born to be able to generate a Deserialize implementation that could aggregate fields. This is why there is a JominiDeserialize derive macro and duplicated and field attribute.

§When to Use

JominiDeserialize is not intended to replace the Deserialize derive macro, as JominiDeserialize has an incredibly narrow scope – to allow efficient deserialization of duplicated and non-consecutive fields. Many field / container attributes are not implemented for JominiDeserialize, so when needed opt to use serde’s Deserialize derive macro.

Since both macros result in an implementation of the Deserialize trait for the given data structure, these macros can be used