Add support for json deserializing enums and options, clean up tests

This commit is contained in:
Erick Tryzelaar 2014-05-29 07:05:19 -07:00
parent 85fd2797a6
commit 27a914cdcf

539
json.rs
View File

@ -316,9 +316,10 @@ enum JsonDeserializerState {
JsonDeserializerValueState(Json),
JsonDeserializerListState(vec::MoveItems<Json>),
JsonDeserializerObjectState(treemap::MoveEntries<String, Json>),
JsonDeserializerEndState,
}
struct JsonDeserializer {
pub struct JsonDeserializer {
stack: Vec<JsonDeserializerState>,
}
@ -380,6 +381,9 @@ impl Iterator<Result<de::Token, ParserError>> for JsonDeserializer {
}
}
}
Some(JsonDeserializerEndState) => {
return Some(Ok(de::End));
}
None => { return None; }
}
}
@ -394,6 +398,131 @@ impl de::Deserializer<ParserError> for JsonDeserializer {
fn syntax_error(&self) -> ParserError {
SyntaxError(InvalidSyntax, 0, 0)
}
// Special case treating options as a nullable value.
#[inline]
fn expect_option<
U: de::Deserializable<ParserError, JsonDeserializer>
>(&mut self, token: de::Token) -> Result<Option<U>, ParserError> {
match token {
de::Null => Ok(None),
token => {
let value: U = try!(de::Deserializable::deserialize_token(self, token));
Ok(Some(value))
}
}
}
#[inline]
fn expect_enum_start(&mut self, token: de::Token, _name: &str, variants: &[&str]) -> Result<uint, ParserError> {
let variant = match token {
de::String(variant) => {
self.stack.push(JsonDeserializerEndState);
variant
}
de::MapStart(_) => {
let state = match self.stack.pop() {
Some(state) => state,
None => { fail!("state machine error, state stack empty"); }
};
let mut iter = match state {
JsonDeserializerObjectState(iter) => iter,
_ => { fail!("state machine error, expected an object"); }
};
let mut variant = None;
let mut fields = None;
for (key, value) in iter {
if key.equiv(&"variant") {
match value {
String(v) => { variant = Some(v); }
value => {
return Err(ExpectedError("String".to_string(),
format!("{}", value)))
}
}
} else if key.equiv(&"fields") {
match value {
List(v) => { fields = Some(v); }
value => {
return Err(ExpectedError("List".to_string(),
format!("{}", value)))
}
}
}
}
let (variant, fields) = match (variant, fields) {
(Some(variant), Some(fields)) => (variant, fields),
(None, _) => {
return Err(MissingFieldError("variant".to_string()))
}
(_, None) => {
return Err(MissingFieldError("fields".to_string()))
}
};
self.stack.push(JsonDeserializerEndState);
for field in fields.move_iter().rev() {
self.stack.push(JsonDeserializerValueState(field));
}
variant
}
token => {
return Err(ExpectedError("String or Object".to_string(),
format!("{}", token)))
}
};
/*
let name = match self.stack.pop() {
String(s) => s,
Object(mut object) => {
let n = match object.pop_equiv(&"variant") {
Some(String(s)) => s,
Some(value) => {
return Err(ExpectedError("String".to_string(),
format!("{}", value)))
}
None => {
return Err(MissingFieldError("variant".to_string()))
}
};
match object.pop_equiv(&"fields") {
Some(List(list)) => {
for field in list.move_iter().rev() {
self.stack.push(JsonDeserializerValueState(field));
}
},
Some(value) => {
return Err(ExpectedError("List".to_string(),
format!("{}", value)))
}
None => {
return Err(MissingFieldError("fields".to_string()))
}
}
n
}
json => {
return Err(ExpectedError("String or Object".to_string(),
format!("{}", json)))
}
};
*/
match variants.iter().position(|v| *v == variant.as_slice()) {
Some(idx) => Ok(idx),
None => Err(UnknownVariantError(variant)),
}
}
}
/// The errors that can arise while parsing a JSON stream.
@ -422,11 +551,15 @@ pub enum ParserError {
/// msg, line, col
SyntaxError(ErrorCode, uint, uint),
IoError(io::IoErrorKind, &'static str),
ExpectedError(String, String),
MissingFieldError(String),
UnknownVariantError(String),
}
// Builder and Parser have the same errors.
pub type BuilderError = ParserError;
/*
#[deriving(Clone, Eq, Show)]
pub enum DecoderError {
ParseError(ParserError),
@ -434,6 +567,7 @@ pub enum DecoderError {
MissingFieldError(String),
UnknownVariantError(String),
}
*/
/// Returns a readable error string for a given error code.
pub fn error_str(error: ErrorCode) -> &'static str {
@ -469,7 +603,7 @@ fn io_error_to_error(io: io::IoError) -> ParserError {
}
pub type EncodeResult = io::IoResult<()>;
pub type DecodeResult<T> = Result<T, DecoderError>;
//pub type DecodeResult<T> = Result<T, DecoderError>;
fn escape_str(s: &str) -> String {
let mut escaped = String::from_str("\"");
@ -1754,7 +1888,7 @@ impl<T: Iterator<char>> de::Deserializer<ParserError> for Parser<T> {
#[inline]
fn expect_enum_start(&mut self, token: de::Token, _name: &str, variants: &[&str]) -> Result<uint, ParserError> {
match token {
Str(name) =>
Str(name) =>
}
@ -2463,7 +2597,7 @@ mod tests {
Object,
};
use super::{Parser, ParserError, from_iter};
use super::{JsonDeserializer, from_json};
use super::{JsonDeserializer, from_json, ToJson};
use super::{
EOFWhileParsingList,
EOFWhileParsingObject,
@ -2472,7 +2606,7 @@ mod tests {
ExpectedColon,
InvalidNumber,
InvalidSyntax,
KeyMustBeAString,
KeyMustBeAString,
TrailingCharacters,
SyntaxError,
};
@ -2483,6 +2617,14 @@ mod tests {
use std::str;
use collections::TreeMap;
macro_rules! treemap {
($($k:expr => $v:expr),*) => ({
let mut _m = ::collections::TreeMap::new();
$(_m.insert($k, $v);)*
_m
})
}
#[deriving(Eq, Show)]
enum Animal {
Dog,
@ -2574,6 +2716,18 @@ mod tests {
}
}
impl ToJson for Inner {
fn to_json(&self) -> Json {
Object(
treemap!(
"a".to_string() => self.a.to_json(),
"b".to_string() => self.b.to_json(),
"c".to_string() => self.c.to_json()
)
)
}
}
#[deriving(Eq, Show)]
struct Outer {
inner: Vec<Inner>,
@ -2622,6 +2776,16 @@ mod tests {
}
}
impl ToJson for Outer {
fn to_json(&self) -> Json {
Object(
treemap!(
"inner".to_string() => self.inner.to_json()
)
)
}
}
/*
fn mk_object(items: &[(String, Json)]) -> Json {
let mut d = box TreeMap::new();
@ -2874,59 +3038,61 @@ mod tests {
}
*/
fn test_parser_err<
fn test_parse_err<
'a,
T: Eq + Show + de::Deserializable<ParserError, Parser<str::Chars<'a>>>
>(errors: &[(&'a str, ParserError)]) {
for &(s, err) in errors.iter() {
for &(s, ref err) in errors.iter() {
let v: Result<T, ParserError> = from_iter(s.chars());
assert_eq!(v, Err(err));
assert_eq!(v.unwrap_err(), *err);
}
}
fn test_parser_ok<
fn test_parse_ok<
'a,
T: Eq + Show + de::Deserializable<ParserError, Parser<str::Chars<'a>>>
T: Eq + Show + ToJson + de::Deserializable<ParserError, Parser<str::Chars<'a>>>
>(errors: &[(&'a str, T)]) {
for &(s, ref value) in errors.iter() {
let v: T = from_iter(s.chars()).unwrap();
assert_eq!(v, *value);
let v: Json = from_iter(s.chars()).unwrap();
assert_eq!(v, value.to_json());
}
}
fn test_json_deserializer_ok<
T: Eq + Show + de::Deserializable<ParserError, JsonDeserializer>
>(errors: &[(Json, T)]) {
for &(ref json, ref value) in errors.iter() {
let v: T = from_json(json.clone()).unwrap();
fn test_json_deserialize_ok<
T: Eq + Show + ToJson + de::Deserializable<ParserError, JsonDeserializer>
>(errors: &[T]) {
for value in errors.iter() {
let v: T = from_json(value.to_json()).unwrap();
assert_eq!(v, *value);
}
}
#[test]
fn test_decode_null() {
test_parser_err::<()>([
fn test_parse_null() {
test_parse_err::<()>([
("n", SyntaxError(InvalidSyntax, 1, 2)),
("nul", SyntaxError(InvalidSyntax, 1, 4)),
("nulla", SyntaxError(TrailingCharacters, 1, 5)),
]);
test_parser_ok([
test_parse_ok([
("null", ()),
]);
test_parser_ok([
("null", Null),
]);
test_json_deserializer_ok([
(Null, ()),
]);
}
#[test]
fn test_decode_bool() {
test_parser_err::<bool>([
fn test_json_deserialize_null() {
test_json_deserialize_ok([
(),
]);
}
#[test]
fn test_parse_bool() {
test_parse_err::<bool>([
("t", SyntaxError(InvalidSyntax, 1, 2)),
("truz", SyntaxError(InvalidSyntax, 1, 4)),
("f", SyntaxError(InvalidSyntax, 1, 2)),
@ -2935,20 +3101,17 @@ mod tests {
("falsea", SyntaxError(TrailingCharacters, 1, 6)),
]);
test_parser_ok([
test_parse_ok([
("true", true),
("false", false),
]);
}
test_parser_ok([
("true", Boolean(true)),
("false", Boolean(false)),
]);
test_json_deserializer_ok([
(Boolean(true), true),
(Boolean(false), false),
#[test]
fn test_json_deserialize_bool() {
test_json_deserialize_ok([
true,
false,
]);
}
@ -2975,8 +3138,8 @@ mod tests {
*/
#[test]
fn test_decode_numbers() {
let errors = [
fn test_parse_numbers() {
test_parse_err::<f64>([
("+", SyntaxError(InvalidSyntax, 1, 1)),
(".", SyntaxError(InvalidSyntax, 1, 1)),
("-", SyntaxError(InvalidNumber, 1, 2)),
@ -2985,14 +3148,9 @@ mod tests {
("1e", SyntaxError(InvalidNumber, 1, 3)),
("1e+", SyntaxError(InvalidNumber, 1, 4)),
("1a", SyntaxError(TrailingCharacters, 1, 2)),
];
]);
for &(s, err) in errors.iter() {
let v: Result<f64, ParserError> = from_iter(s.chars());
assert_eq!(v, Err(err));
}
let values = [
test_parse_ok([
("3", 3.0),
("3.1", 3.1),
("-1.2", -1.2),
@ -3000,12 +3158,20 @@ mod tests {
("0.4e5", 0.4e5),
("0.4e15", 0.4e15),
("0.4e-01", 0.4e-01),
];
]);
}
for &(s, value) in values.iter() {
let v: Result<f64, ParserError> = from_iter(s.chars());
assert_eq!(v, Ok(value));
}
#[test]
fn test_json_deserialize_numbers() {
test_json_deserialize_ok([
3.0,
3.1,
-1.2,
0.4,
0.4e5,
0.4e15,
0.4e-01,
]);
}
/*
@ -3028,33 +3194,39 @@ mod tests {
*/
#[test]
fn test_decode_str() {
let errors = [
fn test_parse_str() {
test_parse_err::<String>([
("\"", SyntaxError(EOFWhileParsingString, 1, 2)),
("\"lol", SyntaxError(EOFWhileParsingString, 1, 5)),
("\"lol\"a", SyntaxError(TrailingCharacters, 1, 6)),
];
]);
for &(s, err) in errors.iter() {
let v: Result<String, ParserError> = from_iter(s.chars());
assert_eq!(v, Err(err));
}
test_parse_ok([
("\"\"", "".to_string()),
("\"foo\"", "foo".to_string()),
("\"\\\"\"", "\"".to_string()),
("\"\\b\"", "\x08".to_string()),
("\"\\n\"", "\n".to_string()),
("\"\\r\"", "\r".to_string()),
("\"\\t\"", "\t".to_string()),
("\"\\u12ab\"", "\u12ab".to_string()),
("\"\\uAB12\"", "\uAB12".to_string()),
]);
}
let s = [("\"\"", ""),
("\"foo\"", "foo"),
("\"\\\"\"", "\""),
("\"\\b\"", "\x08"),
("\"\\n\"", "\n"),
("\"\\r\"", "\r"),
("\"\\t\"", "\t"),
("\"\\u12ab\"", "\u12ab"),
("\"\\uAB12\"", "\uAB12")];
for &(i, o) in s.iter() {
let mut parser = Parser::new(i.chars());
let v: String = de::Deserializable::deserialize(&mut parser).unwrap();
assert_eq!(v.as_slice(), o);
}
#[test]
fn test_json_deserialize_str() {
test_json_deserialize_ok([
"".to_string(),
"foo".to_string(),
"\"".to_string(),
"\x08".to_string(),
"\n".to_string(),
"\r".to_string(),
"\t".to_string(),
"\u12ab".to_string(),
"\uAB12".to_string(),
]);
}
/*
@ -3081,44 +3253,56 @@ mod tests {
*/
#[test]
fn test_decode_list() {
let errors = [
("[", SyntaxError(EOFWhileParsingValue, 1, 2)),
("[ ", SyntaxError(EOFWhileParsingValue, 1, 3)),
("[1", SyntaxError(EOFWhileParsingList, 1, 3)),
("[1,", SyntaxError(EOFWhileParsingValue, 1, 4)),
("[1,]", SyntaxError(InvalidSyntax, 1, 4)),
("[1 2]", SyntaxError(InvalidSyntax, 1, 4)),
fn test_parse_list() {
test_parse_err::<Vec<f64>>([
("[", SyntaxError(EOFWhileParsingValue, 1, 2)),
("[ ", SyntaxError(EOFWhileParsingValue, 1, 3)),
("[1", SyntaxError(EOFWhileParsingList, 1, 3)),
("[1,", SyntaxError(EOFWhileParsingValue, 1, 4)),
("[1,]", SyntaxError(InvalidSyntax, 1, 4)),
("[1 2]", SyntaxError(InvalidSyntax, 1, 4)),
("[]a", SyntaxError(TrailingCharacters, 1, 3)),
];
for &(s, err) in errors.iter() {
let v: Result<Vec<f64>, ParserError> = from_iter(s.chars());
assert_eq!(v, Err(err));
}
]);
let v: Vec<()> = from_iter("[]".chars()).unwrap();
assert_eq!(v, vec![]);
test_parse_ok([
("[]", vec!()),
("[ ]", vec!()),
("[null]", vec!(())),
("[ null ]", vec!(())),
]);
let v: Vec<()> = from_iter("[ ]".chars()).unwrap();
assert_eq!(v, vec![]);
test_parse_ok([
("[true]", vec!(true)),
]);
let v: Vec<()> = from_iter("[null]".chars()).unwrap();
assert_eq!(v, vec![()]);
test_parse_ok([
("[3,1]", vec!(3, 1)),
("[ 3 , 1 ]", vec!(3, 1)),
]);
let v: Vec<()> = from_iter("[ null ]".chars()).unwrap();
assert_eq!(v, vec![()]);
test_parse_ok([
("[[3], [1, 2]]", vec!(vec!(3), vec!(1, 2))),
]);
}
let v: Vec<bool> = from_iter("[true]".chars()).unwrap();
assert_eq!(v, vec![true]);
#[test]
fn test_json_deserialize_list() {
test_json_deserialize_ok([
vec!(),
vec!(()),
]);
let v: Vec<int> = from_iter("[3,1]".chars()).unwrap();
assert_eq!(v, vec![3, 1]);
test_json_deserialize_ok([
vec!(true),
]);
let v: Vec<int> = from_iter("[ 3 , 1 ]".chars()).unwrap();
assert_eq!(v, vec![3, 1]);
test_json_deserialize_ok([
vec!(3, 1),
]);
let v: Vec<Vec<uint>> = from_iter("[[3], [1, 2]]".chars()).unwrap();
assert_eq!(v, vec![vec![3], vec![1, 2]]);
test_json_deserialize_ok([
vec!(vec!(3), vec!(1, 2)),
]);
}
/*
@ -3179,8 +3363,8 @@ mod tests {
*/
#[test]
fn test_decode_object() {
let errors = [
fn test_parse_object() {
test_parse_err::<TreeMap<String, int>>([
("{", SyntaxError(EOFWhileParsingString, 1, 2)),
("{ ", SyntaxError(EOFWhileParsingString, 1, 3)),
("{1", SyntaxError(KeyMustBeAString, 1, 2)),
@ -3193,82 +3377,101 @@ mod tests {
("{\"a\":1 1", SyntaxError(InvalidSyntax, 1, 8)),
("{\"a\":1,", SyntaxError(EOFWhileParsingString, 1, 8)),
("{}a", SyntaxError(TrailingCharacters, 1, 3)),
];
]);
for &(s, err) in errors.iter() {
let v: Result<TreeMap<String, int>, ParserError> = from_iter(s.chars());
assert_eq!(v, Err(err));
}
test_parse_ok([
("{}", treemap!()),
("{ }", treemap!()),
(
"{\"a\":3}",
treemap!("a".to_string() => 3)
),
(
"{ \"a\" : 3 }",
treemap!("a".to_string() => 3)
),
(
"{\"a\":3,\"b\":4}",
treemap!("a".to_string() => 3, "b".to_string() => 4)
),
(
"{ \"a\" : 3 , \"b\" : 4 }",
treemap!("a".to_string() => 3, "b".to_string() => 4),
),
]);
let v: TreeMap<String, int> = from_iter("{}".chars()).unwrap();
let m = TreeMap::new();
assert!(v == m);
let v: TreeMap<String, int> = from_iter("{ }".chars()).unwrap();
let m = TreeMap::new();
assert!(v == m);
let v: TreeMap<String, int> = from_iter("{\"a\":3}".chars()).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
assert!(v == m);
let v: TreeMap<String, int> = from_iter("{\"a\" :3}".chars()).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
assert!(v == m);
let v: TreeMap<String, int> = from_iter("{\"a\" : 3}".chars()).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
assert!(v == m);
let v: TreeMap<String, int> = from_iter("{\"a\": 3, \"b\": 4}".chars()).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
m.insert("b".to_str(), 4);
assert!(v == m);
let v: TreeMap<String, int> = from_iter("{ \"a\": 3, \"b\": 4 }".chars()).unwrap();
let mut m = TreeMap::new();
m.insert("a".to_str(), 3);
m.insert("b".to_str(), 4);
assert!(v == m);
let v: TreeMap<String, TreeMap<String, int>> = from_iter("{\"a\": {\"b\": 3, \"c\": 4}}".chars()).unwrap();
let mut mm = TreeMap::new();
mm.insert("b".to_str(), 3);
mm.insert("c".to_str(), 4);
let mut m = TreeMap::new();
m.insert("a".to_str(), mm);
assert!(v == m);
test_parse_ok([
(
"{\"a\": {\"b\": 3, \"c\": 4}}",
treemap!("a".to_string() => treemap!("b".to_string() => 3, "c".to_string() => 4)),
),
]);
}
#[test]
fn test_decode_struct() {
let s = "{
\"inner\": [
{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
]
}";
let v: Outer = from_iter(s.chars()).unwrap();
assert_eq!(
v,
fn test_json_deserialize_object() {
test_json_deserialize_ok([
treemap!(),
treemap!("a".to_string() => 3),
treemap!("a".to_string() => 3, "b".to_string() => 4),
]);
test_json_deserialize_ok([
treemap!("a".to_string() => treemap!("b".to_string() => 3, "c".to_string() => 4)),
]);
}
#[test]
fn test_parse_struct() {
test_parse_ok([
(
"{
\"inner\": []
}",
Outer {
inner: vec![]
},
),
(
"{
\"inner\": [
{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
]
}",
Outer {
inner: vec![
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
]
},
)
]);
}
#[test]
fn test_json_deserialize_struct() {
test_json_deserialize_ok([
Outer {
inner: vec![
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
]
}
);
},
]);
}
#[test]
fn test_decode_option() {
let value: Result<Option<String>, ParserError> = from_iter("null".chars());
assert_eq!(value, Ok(None));
fn test_parse_option() {
test_parse_ok([
("null", None),
("\"jodhpurs\"", Some("jodhpurs".to_string())),
]);
}
let value: Result<Option<String>, ParserError> = from_iter("\"jodhpurs\"".chars());
assert_eq!(value, Ok(Some("jodhpurs".to_string())));
#[test]
fn test_json_deserialize_option() {
test_json_deserialize_ok([
None,
Some("jodhpurs".to_string()),
]);
}
/*