Allow json missing fields to be treated as a null

Closes #34.
This commit is contained in:
Erick Tryzelaar 2015-03-12 20:44:16 -07:00
parent 5dd53e7ea3
commit dc87288f48
5 changed files with 82 additions and 4 deletions

View File

@ -1192,9 +1192,7 @@ fn declare_visit_map(
quote_stmt!(cx,
let $field = match $field {
Some($field) => $field,
None => {
return Err(::serde::de::Error::missing_field_error($name_str));
}
None => try!(visitor.missing_field($name_str)),
};
)
})

View File

@ -291,6 +291,12 @@ pub trait MapVisitor {
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
fn missing_field<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
where V: Deserialize,
{
Err(Error::missing_field_error(field))
}
}
impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {

View File

@ -543,6 +543,7 @@ impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
}
if self.de.eof() {
println!("here3");
return Err(self.de.error(ErrorCode::EOFWhileParsingValue));
}
@ -573,6 +574,31 @@ impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
Err(self.de.error(ErrorCode::TrailingCharacters))
}
}
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
where V: de::Deserialize,
{
// See if the type can deserialize from a unit.
struct UnitDeserializer;
impl de::Deserializer for UnitDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_none()
}
}
Ok(try!(de::Deserialize::deserialize(&mut UnitDeserializer)))
}
}
struct EnumVisitor<'a, Iter: 'a> {

View File

@ -553,6 +553,31 @@ impl<'a> de::MapVisitor for MapDeserializer<'a> {
}
}
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
where V: de::Deserialize,
{
// See if the type can deserialize from a unit.
struct UnitDeserializer;
impl de::Deserializer for UnitDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_none()
}
}
Ok(try!(de::Deserialize::deserialize(&mut UnitDeserializer)))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}

View File

@ -643,7 +643,7 @@ fn test_parse_object() {
fn test_parse_struct() {
test_parse_err::<Outer>(&[
("[]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)),
("{}", Error::MissingFieldError("inner")),
("{}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)),
("{\"inner\": true}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)),
]);
@ -759,3 +759,26 @@ fn test_multiline_errors() {
("{\n \"foo\":\n \"bar\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 3, 8)),
]);
}
#[test]
fn test_missing_field() {
#[derive(Debug, PartialEq)]
#[derive_deserialize]
struct Foo {
x: Option<u32>,
}
let value: Foo = from_str("{}").unwrap();
assert_eq!(value, Foo { x: None });
let value: Foo = from_str("{\"x\": 5}").unwrap();
assert_eq!(value, Foo { x: Some(5) });
let value: Foo = from_value(Value::Object(treemap!())).unwrap();
assert_eq!(value, Foo { x: None });
let value: Foo = from_value(Value::Object(treemap!(
"x".to_string() => Value::I64(5)
))).unwrap();
assert_eq!(value, Foo { x: Some(5) });
}