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>,
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>,
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,
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,
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.