Serialize and deserialize a tagged newtype variant over unit () as if it was a unit variant.

This commit is contained in:
Tage Johansson 2022-10-21 00:27:46 +02:00
parent 55cf0ac51a
commit 90d28fc314
3 changed files with 42 additions and 3 deletions

View File

@ -1262,6 +1262,17 @@ mod content {
{
match self.content {
Content::Unit => visitor.visit_unit(),
// As a special case, allow deserializing newtype variant containing unit. E.G:
// #[derive(Deserialize)]
// #[serde(tag = "result")]
// enum Response<T> {
// Success(T),
// }
//
// We want {"result": "Success"} to deserialize into `Response<T>`.
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(),
_ => Err(self.invalid_type(&visitor)),
}
}

View File

@ -51,7 +51,6 @@ enum Unsupported {
String,
ByteArray,
Optional,
Unit,
#[cfg(any(feature = "std", feature = "alloc"))]
UnitStruct,
Sequence,
@ -70,7 +69,6 @@ impl Display for Unsupported {
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
#[cfg(any(feature = "std", feature = "alloc"))]
Unsupported::UnitStruct => formatter.write_str("unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
@ -184,7 +182,9 @@ where
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
let mut map = try!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name));
map.end()
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {

View File

@ -2302,6 +2302,34 @@ fn test_internally_tagged_enum_containing_flatten() {
);
}
#[test]
fn test_internally_tagged_enum_new_type_with_unit() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t")]
enum Data {
A(()),
}
assert_tokens(
&Data::A(()),
&[
Token::Map { len: Some(1) },
Token::Str("t"),
Token::Str("A"),
Token::MapEnd,
],
);
assert_ser_tokens(
&Data::A(()),
&[
Token::Map { len: Some(1) },
Token::Str("t"),
Token::Str("A"),
Token::MapEnd,
],
);
}
#[test]
fn test_adjacently_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]