feat(codegen): Add #[serde(deserialize_with="...")]

This allows a field to be deserialized with an expression instead
of the default deserializer. This simplifies deserializing a struct
or enum that contains an external type that doesn't implement
`serde::Deserialize`. This expression is passed a variable
`deserializer` that needs to be used to deserialize the expression.
This commit is contained in:
Erick Tryzelaar
2016-02-15 20:43:11 -08:00
parent 001cb7ab01
commit 40f8e6b061
3 changed files with 207 additions and 15 deletions
+117 -2
View File
@@ -1,5 +1,5 @@
use std::default::Default;
use serde::{Serialize, Serializer};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use token::{
Error,
@@ -10,13 +10,16 @@ use token::{
assert_de_tokens_error
};
trait Trait {
trait Trait: Sized {
fn my_default() -> Self;
fn should_skip(&self) -> bool;
fn serialize_with<S>(&self, ser: &mut S) -> Result<(), S::Error>
where S: Serializer;
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
where D: Deserializer;
}
impl Trait for i32 {
@@ -33,6 +36,16 @@ impl Trait for i32 {
false.serialize(ser)
}
}
fn deserialize_with<D>(de: &mut D) -> Result<Self, D::Error>
where D: Deserializer
{
if try!(Deserialize::deserialize(de)) {
Ok(123)
} else {
Ok(2)
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -622,3 +635,105 @@ fn test_serialize_with_enum() {
]
);
}
#[derive(Debug, PartialEq, Deserialize)]
struct DeserializeWithStruct<B> where B: Trait {
a: i8,
#[serde(deserialize_with="Trait::deserialize_with(deserializer)")]
b: B,
}
#[test]
fn test_deserialize_with_struct() {
assert_de_tokens(
&DeserializeWithStruct {
a: 1,
b: 2,
},
vec![
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(false),
Token::StructEnd,
]
);
assert_de_tokens(
&DeserializeWithStruct {
a: 1,
b: 123,
},
vec![
Token::StructStart("DeserializeWithStruct", Some(2)),
Token::StructSep,
Token::Str("a"),
Token::I8(1),
Token::StructSep,
Token::Str("b"),
Token::Bool(true),
Token::StructEnd,
]
);
}
#[derive(Debug, PartialEq, Deserialize)]
enum DeserializeWithEnum<B> where B: Trait {
Struct {
a: i8,
#[serde(deserialize_with="Trait::deserialize_with(deserializer)")]
b: B,
}
}
#[test]
fn test_deserialize_with_enum() {
assert_de_tokens(
&DeserializeWithEnum::Struct {
a: 1,
b: 2,
},
vec![
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(false),
Token::EnumMapEnd,
]
);
assert_de_tokens(
&DeserializeWithEnum::Struct {
a: 1,
b: 123,
},
vec![
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::EnumMapSep,
Token::Str("b"),
Token::Bool(true),
Token::EnumMapEnd,
]
);
}