Struct serde_with::EnumMap

source ·
pub struct EnumMap;
Expand description

Represent a list of enum values as a map.

This only works if the enum uses the default externally tagged representation. Other enum representations are not supported.

serde data formats often represent externally tagged enums as maps with a single key. The key is the enum variant name, and the value is the variant value. Sometimes a map with multiple keys should be treated like a list of enum values.

Examples

JSON Map with multiple keys

use serde_with::{serde_as, EnumMap};

#[derive(Serialize, Deserialize)]
enum EnumValue {
    Int(i32),
    String(String),
    Unit,
    Tuple(i32, String, bool),
    Struct {
        a: i32,
        b: String,
        c: bool,
    },
}

#[serde_as]
#[derive(Serialize, Deserialize)]
struct VecEnumValues (
    #[serde_as(as = "EnumMap")]
    Vec<EnumValue>,
);

// ---

// This will serialize this list of values
let values = VecEnumValues(vec![
    EnumValue::Int(123),
    EnumValue::String("FooBar".to_string()),
    EnumValue::Int(456),
    EnumValue::String("XXX".to_string()),
    EnumValue::Unit,
    EnumValue::Tuple(1, "Middle".to_string(), false),
    EnumValue::Struct {
        a: 666,
        b: "BBB".to_string(),
        c: true,
    },
]);

// into this JSON map
// Duplicate keys are emitted for identical enum variants.
let expected =
r#"{
  "Int": 123,
  "String": "FooBar",
  "Int": 456,
  "String": "XXX",
  "Unit": null,
  "Tuple": [
    1,
    "Middle",
    false
  ],
  "Struct": {
    "a": 666,
    "b": "BBB",
    "c": true
  }
}"#;

// Both serialization and deserialization work flawlessly.
let serialized = serde_json::to_string_pretty(&values).unwrap();
assert_eq!(expected, serialized);
let deserialized: VecEnumValues = serde_json::from_str(&serialized).unwrap();
assert_eq!(values, deserialized);

XML structure with varying keys

With serde_xml_rs tuple and struct variants are not supported since they fail to roundtrip. The enum may have such variants as long as they are not serialized or deserialized.

use serde_with::{serde_as, EnumMap};

#[derive(Serialize, Deserialize)]
enum EnumValue {
    Int(i32),
    String(String),
    Unit,
}

#[serde_as]
#[derive(Serialize, Deserialize)]
struct VecEnumValues {
    #[serde_as(as = "EnumMap")]
    vec: Vec<EnumValue>,
}

// ---

// This will serialize this list of values
let values = VecEnumValues {
    vec: vec![
        EnumValue::Int(123),
        EnumValue::String("FooBar".to_string()),
        EnumValue::Int(456),
        EnumValue::String("XXX".to_string()),
        EnumValue::Unit,
    ],
};

// into this XML document
// Duplicate keys are emitted for identical enum variants.
let expected = r#"
<?xml version="1.0" encoding="UTF-8"?>
<VecEnumValues>
    <vec>
        <Int>123</Int>
        <String>FooBar</String>
        <Int>456</Int>
        <String>XXX</String>
        <Unit />
    </vec>
</VecEnumValues>"#
// Remove whitespace
.replace("    ", "")
.replace('\n', "");

// Both serialization and deserialization work flawlessly.
let serialized = serde_xml_rs::to_string(&values).unwrap();
assert_eq!(expected, serialized);
let deserialized: VecEnumValues = serde_xml_rs::from_str(&serialized).unwrap();
assert_eq!(values, deserialized);

Trait Implementations§

source§

impl<'de, T> DeserializeAs<'de, Vec<T, Global>> for EnumMapwhere T: Deserialize<'de>,

source§

fn deserialize_as<D>(deserializer: D) -> Result<Vec<T>, D::Error>where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer.
source§

impl<T> SerializeAs<Vec<T, Global>> for EnumMapwhere T: Serialize,

source§

fn serialize_as<S>(source: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error>where S: Serializer,

Serialize this value into the given Serde serializer.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.