diff options
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/de/mod.rs | 51 | ||||
-rw-r--r-- | tests/test_deserialize.rs | 71 |
3 files changed, 115 insertions, 8 deletions
@@ -27,6 +27,7 @@ url = "1.0.0" [dev-dependencies] csv = "0.15" rand = "0.3" +serde_json = "1.0.2" serde_urlencoded = "0.4" [lib] diff --git a/src/de/mod.rs b/src/de/mod.rs index 03e4065..cf2768b 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -505,10 +505,9 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { }, Level::Sequence(_) => { self.deserialize_seq(visitor) - }, Level::Flat(x) => { - visitor.visit_string(x) + ParsableStringDeserializer(x).deserialize_any(visitor) }, Level::Invalid(e) => { Err(de::Error::custom(e)) @@ -593,7 +592,20 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { ) -> Result<V::Value> where V: de::Visitor<'de> { - self.deserialize_seq(visitor) + match self.0 { + Level::Nested(_) => { + self.deserialize_map(visitor) + }, + Level::Sequence(_) => { + self.deserialize_seq(visitor) + }, + Level::Flat(_) => { + self.deserialize_seq(visitor) + }, + Level::Invalid(e) => { + Err(de::Error::custom(e)) + } + } } fn deserialize_tuple<V>( @@ -603,8 +615,20 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { ) -> Result<V::Value> where V: de::Visitor<'de> { - self.deserialize_seq(visitor) - + match self.0 { + Level::Nested(_) => { + self.deserialize_map(visitor) + }, + Level::Sequence(_) => { + self.deserialize_seq(visitor) + }, + Level::Flat(_) => { + self.deserialize_seq(visitor) + }, + Level::Invalid(e) => { + Err(de::Error::custom(e)) + } + } } fn deserialize_tuple_struct<V>( self, @@ -614,8 +638,20 @@ impl<'de> de::Deserializer<'de> for LevelDeserializer { ) -> Result<V::Value> where V: de::Visitor<'de> { - self.deserialize_seq(visitor) - } + match self.0 { + Level::Nested(_) => { + self.deserialize_map(visitor) + }, + Level::Sequence(_) => { + self.deserialize_seq(visitor) + }, + Level::Flat(_) => { + self.deserialize_seq(visitor) + }, + Level::Invalid(e) => { + Err(de::Error::custom(e)) + } + } } fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de> @@ -705,7 +741,6 @@ impl<'de> de::Deserializer<'de> for ParsableStringDeserializer { self.0.into_deserializer().deserialize_any(visitor) } - forward_to_deserialize_any! { map struct diff --git a/tests/test_deserialize.rs b/tests/test_deserialize.rs index 3e0c843..79d1589 100644 --- a/tests/test_deserialize.rs +++ b/tests/test_deserialize.rs @@ -1,7 +1,11 @@ +extern crate serde; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate serde_json as json; extern crate serde_qs as qs; +use std::fmt; use std::collections::HashMap; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -376,3 +380,70 @@ fn deserialize_enum() { let rec_params: E = qs::from_str(params).unwrap(); assert_eq!(rec_params, E::S("Hello World".to_string())); } + + +#[test] +fn deserialize_custom() { + use serde::de::{self, Deserialize, Visitor, Deserializer}; + + #[derive(Deserialize, Debug, Clone, Copy, PartialEq, Serialize)] + #[serde(rename_all = "lowercase")] + enum TestEnum { Foo, Bar } + + #[derive(Deserialize, Debug, Serialize, PartialEq)] + struct TestStruct { + e: TestEnum, + } + + #[derive(Deserialize, Debug, PartialEq)] + struct NestedStruct { + ts: Vec<TupleStruct>, + } + + #[derive(Debug, PartialEq)] + struct TupleStruct(TestEnum, TestStruct); + + impl<'de> serde::de::Deserialize<'de> for TupleStruct { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> + { + deserializer.deserialize_tuple_struct( + "TupleStruct", 2, TupleStructVisitor) + } + } + + struct TupleStructVisitor; + impl<'de> Visitor<'de> for TupleStructVisitor { + type Value = TupleStruct; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "TupleStruct representation") + } + + fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error> + where V: de::MapAccess<'de> + { + let inner_de = de::value::MapAccessDeserializer::new(map); + let test_struct: TestStruct = Deserialize::deserialize(inner_de)?; + + let result = TupleStruct(test_struct.e, test_struct); + Ok(result) + } + } + + + let expected = NestedStruct { + ts: vec![TupleStruct(TestEnum::Bar, TestStruct { e: TestEnum::Bar}), TupleStruct(TestEnum::Foo, TestStruct { e: TestEnum::Foo})], + }; + + let json_struct: NestedStruct = json::from_str(&json!({ + "ts": [{"e": "bar"}, {"e": "foo"}], + }).to_string()).unwrap(); + + let qs_struct: NestedStruct = qs::from_str( + "ts[0][e]=bar&ts[1][e]=foo" + ).unwrap(); + + assert_eq!(qs_struct, json_struct); + assert_eq!(qs_struct, expected); +} |