either/serde_untagged.rs
1//! Untagged serialization/deserialization support for Either<L, R>.
2//!
3//! `Either` uses default, externally-tagged representation.
4//! However, sometimes it is useful to support several alternative types.
5//! For example, we may have a field which is generally Map<String, i32>
6//! but in typical cases Vec<String> would suffice, too.
7//!
8//! ```rust
9//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
10//! use either::Either;
11//! use std::collections::HashMap;
12//!
13//! #[derive(serde::Serialize, serde::Deserialize, Debug)]
14//! #[serde(transparent)]
15//! struct IntOrString {
16//! #[serde(with = "either::serde_untagged")]
17//! inner: Either<Vec<String>, HashMap<String, i32>>
18//! };
19//!
20//! // serialization
21//! let data = IntOrString {
22//! inner: Either::Left(vec!["Hello".to_string()])
23//! };
24//! // notice: no tags are emitted.
25//! assert_eq!(serde_json::to_string(&data)?, r#"["Hello"]"#);
26//!
27//! // deserialization
28//! let data: IntOrString = serde_json::from_str(
29//! r#"{"a": 0, "b": 14}"#
30//! )?;
31//! println!("found {:?}", data);
32//! # Ok(())
33//! # }
34//! ```
35
36use serde::{Deserialize, Deserializer, Serialize, Serializer};
37
38#[derive(serde::Serialize, serde::Deserialize)]
39#[serde(untagged)]
40enum Either<L, R> {
41 Left(L),
42 Right(R),
43}
44
45pub fn serialize<L, R, S>(this: &super::Either<L, R>, serializer: S) -> Result<S::Ok, S::Error>
46where
47 S: Serializer,
48 L: Serialize,
49 R: Serialize,
50{
51 let untagged = match this {
52 super::Either::Left(left) => Either::Left(left),
53 super::Either::Right(right) => Either::Right(right),
54 };
55 untagged.serialize(serializer)
56}
57
58pub fn deserialize<'de, L, R, D>(deserializer: D) -> Result<super::Either<L, R>, D::Error>
59where
60 D: Deserializer<'de>,
61 L: Deserialize<'de>,
62 R: Deserialize<'de>,
63{
64 match Either::deserialize(deserializer) {
65 Ok(Either::Left(left)) => Ok(super::Either::Left(left)),
66 Ok(Either::Right(right)) => Ok(super::Either::Right(right)),
67 Err(error) => Err(error),
68 }
69}