Merge pull request #111 from oli-obk/master

tuple enums with single element should not be a json-array
This commit is contained in:
Erick Tryzelaar 2015-07-29 13:35:43 -07:00
commit 0058e3a8d4
12 changed files with 190 additions and 96 deletions

View File

@ -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,
{

View File

@ -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>

View File

@ -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,

View File

@ -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)))

View File

@ -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)
}
}

View File

@ -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());

View File

@ -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,

View File

@ -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

View File

@ -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)
}

View File

@ -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![

View File

@ -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}}",
);

View File

@ -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,