mirror of
https://github.com/serde-rs/serde.git
synced 2025-09-28 13:30:48 +00:00
Get deserializing json objects into structs working
This commit is contained in:
parent
38a468ad23
commit
bf58f7999f
87
de.rs
87
de.rs
@ -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
156
json.rs
@ -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());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user