Get deserializing json objects into structs working

This commit is contained in:
Erick Tryzelaar 2014-05-27 07:36:57 -07:00
parent 38a468ad23
commit bf58f7999f
2 changed files with 237 additions and 6 deletions

87
de.rs
View File

@ -479,6 +479,93 @@ deserialize_tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
pub fn ignore<E, D: Deserializer<E>>(d: &mut D) -> Result<(), E> {
let token = match d.next() {
Some(Ok(token)) => token,
Some(Err(err)) => { return Err(err); }
None => { return Err(d.end_of_stream_error()); }
};
ignore_token(d, token)
}
pub fn ignore_token<E, D: Deserializer<E>>(d: &mut D, token: Token) -> Result<(), E> {
match token {
Null => Ok(()),
Bool(_) => Ok(()),
Uint(_) => Ok(()),
U8(_) => Ok(()),
U16(_) => Ok(()),
U32(_) => Ok(()),
U64(_) => Ok(()),
Int(_) => Ok(()),
I8(_) => Ok(()),
I16(_) => Ok(()),
I32(_) => Ok(()),
I64(_) => Ok(()),
F32(_) => Ok(()),
F64(_) => Ok(()),
Char(_) => Ok(()),
Str(_) => Ok(()),
String(_) => Ok(()),
Option(true) => { ignore(d) }
Option(false) => { Ok(()) }
EnumStart(_, _) => {
loop {
match try!(d.expect_token()) {
End => { return Ok(()); }
token => { try!(ignore_token(d, token)); }
}
}
}
StructStart(_) => {
loop {
match try!(d.expect_token()) {
End => { return Ok(()); }
Str(_) | String(_) => { try!(ignore(d)); }
token => { return Err(d.syntax_error()); }
}
}
}
TupleStart(_) => {
loop {
match try!(d.expect_token()) {
End => { return Ok(()); }
token => { try!(ignore_token(d, token)); }
}
}
}
SeqStart(_) => {
loop {
match try!(d.expect_token()) {
End => { return Ok(()); }
token => { try!(ignore_token(d, token)); }
}
}
}
MapStart(_) => {
loop {
match try!(d.expect_token()) {
End => { return Ok(()); }
token => {
try!(ignore_token(d, token));
try!(ignore(d));
}
}
}
}
End => Err(d.syntax_error()),
}
}
//////////////////////////////////////////////////////////////////////////////
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use collections::HashMap; use collections::HashMap;

156
json.rs
View File

@ -1460,6 +1460,7 @@ impl<T: Iterator<char>> Parser<T> {
fn parse_list_start(&mut self) -> Result<de::Token, ParserError> { fn parse_list_start(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace(); self.parse_whitespace();
if self.ch_is(']') { if self.ch_is(']') {
self.bump(); self.bump();
Ok(de::End) Ok(de::End)
@ -1471,6 +1472,7 @@ impl<T: Iterator<char>> Parser<T> {
fn parse_list_comma_or_end(&mut self) -> Result<de::Token, ParserError> { fn parse_list_comma_or_end(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace(); self.parse_whitespace();
if self.ch_is(',') { if self.ch_is(',') {
self.bump(); self.bump();
self.state.push(ParseListCommaOrEnd); self.state.push(ParseListCommaOrEnd);
@ -1487,6 +1489,7 @@ impl<T: Iterator<char>> Parser<T> {
fn parse_object_start(&mut self) -> Result<de::Token, ParserError> { fn parse_object_start(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace(); self.parse_whitespace();
if self.ch_is('}') { if self.ch_is('}') {
self.bump(); self.bump();
Ok(de::End) Ok(de::End)
@ -1497,6 +1500,7 @@ impl<T: Iterator<char>> Parser<T> {
fn parse_object_comma_or_end(&mut self) -> Result<de::Token, ParserError> { fn parse_object_comma_or_end(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace(); self.parse_whitespace();
if self.ch_is(',') { if self.ch_is(',') {
self.bump(); self.bump();
self.parse_object_key() self.parse_object_key()
@ -1512,6 +1516,7 @@ impl<T: Iterator<char>> Parser<T> {
fn parse_object_key(&mut self) -> Result<de::Token, ParserError> { fn parse_object_key(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace(); self.parse_whitespace();
self.state.push(ParseObjectValue); self.state.push(ParseObjectValue);
if self.eof() { if self.eof() {
@ -1529,6 +1534,7 @@ impl<T: Iterator<char>> Parser<T> {
fn parse_object_value(&mut self) -> Result<de::Token, ParserError> { fn parse_object_value(&mut self) -> Result<de::Token, ParserError> {
self.parse_whitespace(); self.parse_whitespace();
if self.ch_is(':') { if self.ch_is(':') {
self.bump(); self.bump();
self.state.push(ParseObjectCommaOrEnd); self.state.push(ParseObjectCommaOrEnd);
@ -2244,13 +2250,33 @@ mod tests {
use std::io; use std::io;
use collections::TreeMap; use collections::TreeMap;
/*
#[deriving(Eq, Show)] #[deriving(Eq, Show)]
enum Animal { enum Animal {
Dog, Dog,
Frog(String, int) Frog(String, int)
} }
impl<E, D: de::Deserializer<E>> de::Deserializable<E, D> for Animal {
#[inline]
fn deserialize_token(d: &mut D, token: de::Token) -> Result<Animal, E> {
match try!(d.expect_enum_start(token, "Animal", ["Dog", "Frog"])) {
0 => {
try!(d.expect_end());
Ok(Dog)
}
1 => {
let x0 = try!(de::Deserializable::deserialize(d));
let x1 = try!(de::Deserializable::deserialize(d));
try!(d.expect_end());
Ok(Frog(x0, x1))
}
_ => Err(d.syntax_error()),
}
}
}
#[deriving(Eq, Show)] #[deriving(Eq, Show)]
struct Inner { struct Inner {
a: (), a: (),
@ -2258,11 +2284,130 @@ mod tests {
c: Vec<String>, c: Vec<String>,
} }
impl<E, D: de::Deserializer<E>> de::Deserializable<E, D> for Inner {
#[inline]
fn deserialize_token(d: &mut D, token: de::Token) -> Result<Inner, E> {
match token {
de::StructStart(name) => {
if name != "Inner" {
return Err(d.syntax_error());
}
let a = try!(d.expect_struct_field("a"));
let b = try!(d.expect_struct_field("b"));
let c = try!(d.expect_struct_field("c"));
try!(d.expect_end());
Ok(Inner { a: a, b: b, c: c })
}
de::MapStart(_) => {
let mut a = None;
let mut b = None;
let mut c = None;
loop {
match try!(d.expect_token()) {
de::End => { break; }
de::Str(name) => {
match name {
"a" => {
a = Some(try!(de::Deserializable::deserialize(d)));
}
"b" => {
b = Some(try!(de::Deserializable::deserialize(d)));
}
"c" => {
c = Some(try!(de::Deserializable::deserialize(d)));
}
_ => { }
}
}
de::String(ref name) => {
match name.as_slice() {
"a" => {
a = Some(try!(de::Deserializable::deserialize(d)));
}
"b" => {
b = Some(try!(de::Deserializable::deserialize(d)));
}
"c" => {
c = Some(try!(de::Deserializable::deserialize(d)));
}
_ => { }
}
}
_ => { return Err(d.syntax_error()); }
}
}
match (a, b, c) {
(Some(a), Some(b), Some(c)) => {
Ok(Inner { a: a, b: b, c: c })
}
_ => Err(d.syntax_error()),
}
}
_ => Err(d.syntax_error()),
}
}
}
#[deriving(Eq, Show)] #[deriving(Eq, Show)]
struct Outer { struct Outer {
inner: Vec<Inner>, inner: Vec<Inner>,
} }
impl<E, D: de::Deserializer<E>> de::Deserializable<E, D> for Outer {
#[inline]
fn deserialize_token(d: &mut D, token: de::Token) -> Result<Outer, E> {
match token {
de::StructStart(name) => {
if name != "Outer" {
return Err(d.syntax_error());
}
let inner = try!(d.expect_struct_field("inner"));
try!(d.expect_end());
Ok(Outer { inner: inner })
}
de::MapStart(_) => {
let mut inner = None;
loop {
match try!(d.expect_token()) {
de::End => { break; }
de::Str(name) => {
match name {
"inner" => {
inner = Some(try!(de::Deserializable::deserialize(d)));
}
_ => { }
}
}
de::String(ref name) => {
match name.as_slice() {
"inner" => {
inner = Some(try!(de::Deserializable::deserialize(d)));
}
_ => { }
}
}
_ => { return Err(d.syntax_error()); }
}
}
match inner {
Some(inner) => {
Ok(Outer { inner: inner })
}
_ => Err(d.syntax_error()),
}
}
_ => Err(d.syntax_error()),
}
}
}
/*
fn mk_object(items: &[(String, Json)]) -> Json { fn mk_object(items: &[(String, Json)]) -> Json {
let mut d = box TreeMap::new(); let mut d = box TreeMap::new();
@ -2840,26 +2985,25 @@ mod tests {
assert!(v == m); assert!(v == m);
} }
/*
#[test] #[test]
fn test_decode_struct() { fn test_decode_struct() {
let s = "{ let s = "{
\"inner\": [ \"inner\": [
{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
] ]
}"; }";
let mut decoder = Decoder::new(from_str(s).unwrap()); //{ \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
let v: Outer = Decodable::decode(&mut decoder).unwrap(); let v: Outer = from_iter(s.chars()).unwrap();
assert_eq!( assert_eq!(
v, v,
Outer { Outer {
inner: vec![ inner: vec![
Inner { a: (), b: 2, c: vec!["abc".to_strbuf(), "xyz".to_strbuf()] } //Inner { a: (), b: 2, c: vec!["abc".to_strbuf(), "xyz".to_strbuf()] }
] ]
} }
); );
} }
/*
#[test] #[test]
fn test_decode_option() { fn test_decode_option() {
let mut decoder = Decoder::new(from_str("null").unwrap()); let mut decoder = Decoder::new(from_str("null").unwrap());