Merge pull request #111 from oli-obk/master
tuple enums with single element should not be a json-array
This commit is contained in:
commit
0058e3a8d4
@ -571,6 +571,11 @@ pub trait VariantVisitor {
|
||||
Err(Error::syntax_error())
|
||||
}
|
||||
|
||||
/// `visit_simple` is called when deserializing a variant with a single value.
|
||||
fn visit_simple<T: Deserialize>(&mut self) -> Result<T, Self::Error> {
|
||||
Err(Error::syntax_error())
|
||||
}
|
||||
|
||||
/// `visit_seq` is called when deserializing a tuple-like variant.
|
||||
fn visit_seq<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor
|
||||
@ -601,6 +606,10 @@ impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
|
||||
(**self).visit_unit()
|
||||
}
|
||||
|
||||
fn visit_simple<D: Deserialize>(&mut self) -> Result<D, T::Error> {
|
||||
(**self).visit_simple()
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
|
||||
where V: Visitor,
|
||||
{
|
||||
|
@ -125,6 +125,14 @@ pub trait Serializer {
|
||||
self.visit_unit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_enum_simple<T>(&mut self,
|
||||
_name: &str,
|
||||
_variant: &str,
|
||||
_value: T,
|
||||
) -> Result<(), Self::Error>
|
||||
where T: Serialize;
|
||||
|
||||
fn visit_none(&mut self) -> Result<(), Self::Error>;
|
||||
|
||||
fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error>
|
||||
|
@ -556,6 +556,12 @@ fn deserialize_variant(
|
||||
Ok($type_ident::$variant_ident)
|
||||
})
|
||||
}
|
||||
ast::TupleVariantKind(ref args) if args.len() == 1 => {
|
||||
quote_expr!(cx, {
|
||||
let val = try!(visitor.visit_simple());
|
||||
Ok($type_ident::$variant_ident(val))
|
||||
})
|
||||
}
|
||||
ast::TupleVariantKind(ref args) => {
|
||||
deserialize_tuple_variant(
|
||||
cx,
|
||||
|
@ -296,7 +296,25 @@ fn serialize_variant(
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
ast::TupleVariantKind(ref args) if args.len() == 1 => {
|
||||
let field = builder.id("__simple_value");
|
||||
let field = builder.pat().ref_id(field);
|
||||
let pat = builder.pat().enum_()
|
||||
.id(type_ident).id(variant_ident).build()
|
||||
.with_pats(Some(field).into_iter())
|
||||
.build();
|
||||
quote_arm!(cx,
|
||||
$pat => {
|
||||
::serde::ser::Serializer::visit_enum_simple(
|
||||
serializer,
|
||||
$type_name,
|
||||
$variant_name,
|
||||
__simple_value,
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
ast::TupleVariantKind(ref args) => {
|
||||
let fields: Vec<ast::Ident> = (0 .. args.len())
|
||||
.map(|i| builder.id(format!("__field{}", i)))
|
||||
|
@ -632,20 +632,22 @@ impl<Iter> de::VariantVisitor for Deserializer<Iter>
|
||||
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
||||
where V: de::Deserialize
|
||||
{
|
||||
de::Deserialize::deserialize(self)
|
||||
let val = try!(de::Deserialize::deserialize(self));
|
||||
try!(self.parse_object_colon());
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
fn visit_unit(&mut self) -> Result<(), Error> {
|
||||
try!(self.parse_object_colon());
|
||||
de::Deserialize::deserialize(self)
|
||||
}
|
||||
|
||||
fn visit_simple<T: de::Deserialize>(&mut self) -> Result<T, Error> {
|
||||
de::Deserialize::deserialize(self)
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
try!(self.parse_object_colon());
|
||||
|
||||
de::Deserializer::visit(self, visitor)
|
||||
}
|
||||
|
||||
@ -654,8 +656,6 @@ impl<Iter> de::VariantVisitor for Deserializer<Iter>
|
||||
visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
try!(self.parse_object_colon());
|
||||
|
||||
de::Deserializer::visit(self, visitor)
|
||||
}
|
||||
}
|
||||
|
@ -61,12 +61,12 @@
|
||||
//! //#![feature(custom_derive, plugin)]
|
||||
//! //#![plugin(serde_macros)]
|
||||
//!
|
||||
//! extern crate serde;
|
||||
//! extern crate serde_json;
|
||||
//!
|
||||
//! use serde_json::{self, Value};
|
||||
//! use serde_json::Value;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let data: Value = json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
|
||||
//! let data: Value = serde_json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
|
||||
//! println!("data: {:?}", data);
|
||||
//! // data: {"bar":"baz","foo":13}
|
||||
//! println!("object? {}", data.is_object());
|
||||
|
@ -171,6 +171,22 @@ impl<W, F> ser::Serializer for Serializer<W, F>
|
||||
self.formatter.close(&mut self.writer, b'}')
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_enum_simple<T>(&mut self,
|
||||
_name: &str,
|
||||
variant: &str,
|
||||
value: T,
|
||||
) -> io::Result<()>
|
||||
where T: ser::Serialize,
|
||||
{
|
||||
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||
try!(self.formatter.comma(&mut self.writer, true));
|
||||
try!(self.visit_str(variant));
|
||||
try!(self.formatter.colon(&mut self.writer));
|
||||
try!(value.serialize(self));
|
||||
self.formatter.close(&mut self.writer, b'}')
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
|
||||
where V: ser::SeqVisitor,
|
||||
|
@ -471,6 +471,22 @@ impl ser::Serializer for Serializer {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_enum_simple<T>(&mut self,
|
||||
_name: &str,
|
||||
variant: &str,
|
||||
value: T,
|
||||
) -> Result<(), ()>
|
||||
where T: ser::Serialize,
|
||||
{
|
||||
let mut values = BTreeMap::new();
|
||||
values.insert(variant.to_string(), to_value(&value));
|
||||
|
||||
self.state.push(State::Value(Value::Object(values)));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), ()>
|
||||
where V: ser::SeqVisitor,
|
||||
@ -687,33 +703,19 @@ impl de::Deserializer for Deserializer {
|
||||
|
||||
let mut iter = value.into_iter();
|
||||
|
||||
let value = match iter.next() {
|
||||
Some((variant, Value::Array(fields))) => {
|
||||
self.value = Some(Value::String(variant));
|
||||
|
||||
let len = fields.len();
|
||||
try!(visitor.visit(SeqDeserializer {
|
||||
de: self,
|
||||
iter: fields.into_iter(),
|
||||
len: len,
|
||||
}))
|
||||
}
|
||||
Some((variant, Value::Object(fields))) => {
|
||||
let len = fields.len();
|
||||
try!(visitor.visit(MapDeserializer {
|
||||
de: self,
|
||||
iter: fields.into_iter(),
|
||||
value: Some(Value::String(variant)),
|
||||
len: len,
|
||||
}))
|
||||
}
|
||||
Some(_) => { return Err(de::Error::syntax_error()); }
|
||||
None => { return Err(de::Error::syntax_error()); }
|
||||
let (variant, value) = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => return Err(de::Error::syntax_error()),
|
||||
};
|
||||
|
||||
// enums are encoded in json as maps with a single key:value pair
|
||||
match iter.next() {
|
||||
Some(_) => Err(de::Error::syntax_error()),
|
||||
None => Ok(value)
|
||||
None => visitor.visit(VariantDeserializer {
|
||||
de: self,
|
||||
val: Some(value),
|
||||
variant: Some(Value::String(variant)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -723,6 +725,67 @@ impl de::Deserializer for Deserializer {
|
||||
}
|
||||
}
|
||||
|
||||
struct VariantDeserializer<'a> {
|
||||
de: &'a mut Deserializer,
|
||||
val: Option<Value>,
|
||||
variant: Option<Value>,
|
||||
}
|
||||
|
||||
impl<'a> de::VariantVisitor for VariantDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
||||
where V: de::Deserialize,
|
||||
{
|
||||
de::Deserialize::deserialize(&mut Deserializer::new(self.variant.take().unwrap()))
|
||||
}
|
||||
|
||||
fn visit_unit(&mut self) -> Result<(), Error>
|
||||
{
|
||||
de::Deserialize::deserialize(&mut Deserializer::new(self.val.take().unwrap()))
|
||||
}
|
||||
|
||||
fn visit_simple<D: de::Deserialize>(&mut self) -> Result<D, Error>
|
||||
{
|
||||
de::Deserialize::deserialize(&mut Deserializer::new(self.val.take().unwrap()))
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
if let Value::Array(fields) = self.val.take().unwrap() {
|
||||
de::Deserializer::visit(
|
||||
&mut SeqDeserializer {
|
||||
de: self.de,
|
||||
len: fields.len(),
|
||||
iter: fields.into_iter(),
|
||||
},
|
||||
visitor,
|
||||
)
|
||||
} else {
|
||||
Err(de::Error::syntax_error())
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_map<V>(&mut self, _fields: &'static[&'static str], visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
if let Value::Object(fields) = self.val.take().unwrap() {
|
||||
de::Deserializer::visit(
|
||||
&mut MapDeserializer {
|
||||
de: self.de,
|
||||
len: fields.len(),
|
||||
iter: fields.into_iter(),
|
||||
value: None,
|
||||
},
|
||||
visitor,
|
||||
)
|
||||
} else {
|
||||
Err(de::Error::syntax_error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqDeserializer<'a> {
|
||||
de: &'a mut Deserializer,
|
||||
iter: vec::IntoIter<Value>,
|
||||
@ -773,35 +836,6 @@ impl<'a> de::SeqVisitor for SeqDeserializer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> de::VariantVisitor for SeqDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
||||
where V: de::Deserialize,
|
||||
{
|
||||
de::Deserialize::deserialize(self.de)
|
||||
}
|
||||
|
||||
fn visit_unit(&mut self) -> Result<(), Error>
|
||||
{
|
||||
de::Deserialize::deserialize(self)
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
de::Deserializer::visit(self, visitor)
|
||||
}
|
||||
|
||||
fn visit_map<V>(&mut self,
|
||||
_fields: &'static [&'static str],
|
||||
visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
de::Deserializer::visit(self, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct MapDeserializer<'a> {
|
||||
de: &'a mut Deserializer,
|
||||
iter: btree_map::IntoIter<String, Value>,
|
||||
@ -884,35 +918,6 @@ impl<'a> de::Deserializer for MapDeserializer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> de::VariantVisitor for MapDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
||||
where V: de::Deserialize,
|
||||
{
|
||||
self.de.value = self.value.take();
|
||||
de::Deserialize::deserialize(self.de)
|
||||
}
|
||||
|
||||
fn visit_unit(&mut self) -> Result<(), Error> {
|
||||
de::Deserialize::deserialize(self)
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
de::Deserializer::visit(self, visitor)
|
||||
}
|
||||
|
||||
fn visit_map<V>(&mut self,
|
||||
_fields: &'static [&'static str],
|
||||
visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
de::Deserializer::visit(self, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shortcut function to encode a `T` into a JSON `Value`
|
||||
pub fn to_value<T>(value: &T) -> Value
|
||||
where T: ser::Serialize
|
||||
|
@ -39,6 +39,15 @@ impl serde::Serializer for BytesSerializer {
|
||||
Err(Error)
|
||||
}
|
||||
|
||||
fn visit_enum_simple<T>(&mut self,
|
||||
_name: &str,
|
||||
_variant: &str,
|
||||
_value: T,
|
||||
) -> Result<(), Error>
|
||||
{
|
||||
Err(Error)
|
||||
}
|
||||
|
||||
fn visit_bool(&mut self, _v: bool) -> Result<(), Error> {
|
||||
Err(Error)
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ enum Animal {
|
||||
Dog,
|
||||
Frog(String, Vec<isize>),
|
||||
Cat { age: usize, name: String },
|
||||
|
||||
AntHive(Vec<String>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@ -534,6 +534,10 @@ fn test_write_enum() {
|
||||
Animal::Cat { age: 5, name: "Kate".to_string() },
|
||||
"{\"Cat\":{\"age\":5,\"name\":\"Kate\"}}"
|
||||
),
|
||||
(
|
||||
Animal::AntHive(vec!["Bob".to_string(), "Stuart".to_string()]),
|
||||
"{\"AntHive\":[\"Bob\",\"Stuart\"]}",
|
||||
),
|
||||
]);
|
||||
|
||||
test_pretty_encode_ok(&[
|
||||
@ -976,6 +980,10 @@ fn test_parse_enum() {
|
||||
" { \"Cat\" : { \"age\" : 5 , \"name\" : \"Kate\" } } ",
|
||||
Animal::Cat { age: 5, name: "Kate".to_string() },
|
||||
),
|
||||
(
|
||||
" { \"AntHive\" : [\"Bob\", \"Stuart\"] } ",
|
||||
Animal::AntHive(vec!["Bob".to_string(), "Stuart".to_string()]),
|
||||
),
|
||||
]);
|
||||
|
||||
test_parse_ok(vec![
|
||||
|
@ -473,13 +473,13 @@ fn test_lifetimes() {
|
||||
let lifetime = Lifetimes::LifetimeSeq(&value);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&lifetime).unwrap(),
|
||||
"{\"LifetimeSeq\":[5]}"
|
||||
"{\"LifetimeSeq\":5}"
|
||||
);
|
||||
|
||||
let lifetime = Lifetimes::NoLifetimeSeq(5);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&lifetime).unwrap(),
|
||||
"{\"NoLifetimeSeq\":[5]}"
|
||||
"{\"NoLifetimeSeq\":5}"
|
||||
);
|
||||
|
||||
let value = 5;
|
||||
@ -515,8 +515,8 @@ fn test_generic() {
|
||||
declare_tests!(
|
||||
GenericStruct<u32> : GenericStruct { x: 5 } => "{\"x\":5}",
|
||||
GenericTupleStruct<u32> : GenericTupleStruct(5) => "[5]",
|
||||
GenericEnumSeq<u32, u32> : GenericEnumSeq::Ok(5) => "{\"Ok\":[5]}",
|
||||
GenericEnumSeq<u32, u32> : GenericEnumSeq::Err(5) => "{\"Err\":[5]}",
|
||||
GenericEnumSeq<u32, u32> : GenericEnumSeq::Ok(5) => "{\"Ok\":5}",
|
||||
GenericEnumSeq<u32, u32> : GenericEnumSeq::Err(5) => "{\"Err\":5}",
|
||||
GenericEnumMap<u32, u32> : GenericEnumMap::Ok { x: 5 } => "{\"Ok\":{\"x\":5}}",
|
||||
GenericEnumMap<u32, u32> : GenericEnumMap::Err { x: 5 } => "{\"Err\":{\"x\":5}}",
|
||||
);
|
||||
|
@ -27,6 +27,8 @@ pub enum Token<'a> {
|
||||
UnitStruct(&'a str),
|
||||
EnumUnit(&'a str, &'a str),
|
||||
|
||||
EnumSimple(&'a str, &'a str),
|
||||
|
||||
SeqStart(Option<usize>),
|
||||
TupleStructStart(&'a str, Option<usize>),
|
||||
EnumSeqStart(&'a str, &'a str, Option<usize>),
|
||||
@ -80,6 +82,17 @@ impl<'a> Serializer for AssertSerializer<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_enum_simple<T>(&mut self,
|
||||
name: &str,
|
||||
variant: &str,
|
||||
value: T,
|
||||
) -> Result<(), ()>
|
||||
where T: Serialize,
|
||||
{
|
||||
assert_eq!(self.iter.next(), Some(Token::EnumSimple(name, variant)));
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn visit_unit_struct(&mut self, name: &str) -> Result<(), ()> {
|
||||
assert_eq!(self.iter.next().unwrap(), Token::UnitStruct(name));
|
||||
Ok(())
|
||||
@ -301,6 +314,7 @@ struct Struct {
|
||||
#[derive(Serialize)]
|
||||
enum Enum {
|
||||
Unit,
|
||||
One(i32),
|
||||
Seq(i32, i32),
|
||||
Map { a: i32, b: i32 },
|
||||
}
|
||||
@ -554,6 +568,7 @@ declare_tests! {
|
||||
}
|
||||
test_enum {
|
||||
Enum::Unit => vec![Token::EnumUnit("Enum", "Unit")],
|
||||
Enum::One(42) => vec![Token::EnumSimple("Enum", "One"), Token::I32(42)],
|
||||
Enum::Seq(1, 2) => vec![
|
||||
Token::EnumSeqStart("Enum", "Seq", Some(2)),
|
||||
Token::SeqSep,
|
||||
|
Loading…
x
Reference in New Issue
Block a user