pub fn deserialize_option<'de, D, T>(
    deserializer: D
) -> Result<Option<T>, D::Error> where
    D: Deserializer<'de>,
    T: Deserialize<'de>, 
Expand description

Deserialize an Option in a way that is supported by the s-expression format.

Example

#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields, rename = "size")]
struct Size(f32, f32);

#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields, rename = "thickness")]
struct Thickness(f32);

#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields, rename = "font")]
struct Font {
	size: Size,

	// This attribute enables our custom deserialize logic.
	#[serde(deserialize_with = "serde_kicad_sexpr::deserialize_option")]
	thickness: Option<Thickness>,

	bold: bool
}

Description

The s-expression format is not only not self-describing, but also does not provide any way to see if a value is “missing” (i.e. None) without knowing its type. Unfortunately, serde expects us to decide if the value is present before we know its type: In the above example, we have the input string "bold)" and need to know if thickness is present or not, without knowing that thickness is an s-expr and not, say, an enum that has a variant called bold.

This custom deserialize logic therefore avoids calling Deserializer::deserialize_option alltogether. Instead, we’ll try to deserialize the value as if it was present, and return None if the deserializer returns an error before calling the visitor. This is likely indicative of a type error, that would indicate a missing value.

Drawbacks

Using this deserialize logic might hide errors in the input. If this optional value is the last value that gets deserialized, and the deserialization failed due to some error other than a type error, it might get hidden.

Also, if trying to deserialize the value alters the state of the deserializer, it could lead to incorrect deserialization.