diff --git a/json/src/de.rs b/json/src/de.rs index 08b8ebf96..9f526e479 100644 --- a/json/src/de.rs +++ b/json/src/de.rs @@ -6,6 +6,7 @@ use std::char; use std::i32; use std::io; use std::str; +use std::marker::PhantomData; use serde::de; use serde::iter::LineColIterator; @@ -828,3 +829,48 @@ pub fn from_str(s: &str) -> Result { from_slice(s.as_bytes()) } + +/// Iterator over parsed JSON values +pub struct JSONStream + where Iter: Iterator>, + T: de::Deserialize +{ + deser: Deserializer, + _marker: PhantomData, +} + +/// Iterator over parsed JSON values +impl JSONStream + where Iter:Iterator>, + T: de::Deserialize { + /// Returns Iterator of decoded JSON value from an iterator over + /// `Iterator>`. + pub fn new(i: Iter) -> JSONStream { + JSONStream { + deser: Deserializer::new(i), + _marker: PhantomData + } + } +} + +impl Iterator for JSONStream + where Iter:Iterator>, + T: de::Deserialize { + type Item = Result; + fn next(&mut self) -> Option> { + // skip whitespaces, if any + // this helps with trailing whitespaces, since whitespaces between + // values are handled for us. + if let Err(e) = self.deser.parse_whitespace() { + return Some(Err(e)) + }; + match self.deser.eof() { + Ok(true) => None, + Ok(false) => match de::Deserialize::deserialize(&mut self.deser) { + Ok(v) => Some(Ok(v)), + Err(e) => Some(Err(e)) + }, + Err(e) => Some(Err(e)) + } + } +} diff --git a/json/src/lib.rs b/json/src/lib.rs index 815d06486..f28c5ae45 100644 --- a/json/src/lib.rs +++ b/json/src/lib.rs @@ -53,14 +53,14 @@ //! Address: Address, //! PhoneNumbers: Vec //! } -//! +//! //! #[derive(Serialize, Deserialize)] //! struct Address { //! Street: String, //! City: String, //! Country: String //! } -//! ``` +//! ``` //! //! # Type-based Serialization and Deserialization //! @@ -115,12 +115,13 @@ //! ``` #![deny(missing_docs)] - extern crate num; +extern crate core; extern crate serde; pub use self::de::{ Deserializer, + JSONStream, from_iter, from_reader, from_slice, diff --git a/json_tests/tests/test_json.rs b/json_tests/tests/test_json.rs index d5ad4c9a9..b1ceeedf4 100644 --- a/json_tests/tests/test_json.rs +++ b/json_tests/tests/test_json.rs @@ -12,6 +12,7 @@ use serde::bytes::{ByteBuf, Bytes}; use serde_json::{ self, Value, + JSONStream, from_str, from_value, to_value, @@ -1393,3 +1394,48 @@ fn test_byte_buf_de() { let v: ByteBuf = serde_json::from_str("[1, 2, 3]").unwrap(); assert_eq!(v, bytes); } + +#[test] +fn test_json_stream_newlines() { + let stream = "{\"x\":39} {\"x\":40}{\"x\":41}\n{\"x\":42}".to_string(); + let mut parsed:JSONStream = JSONStream::new( + stream.as_bytes().iter().map(|byte| Ok(*byte))); + assert_eq!(parsed.next().unwrap().ok().unwrap().lookup("x").unwrap(), + &Value::U64(39)); + assert_eq!(parsed.next().unwrap().ok().unwrap().lookup("x").unwrap(), + &Value::U64(40)); + assert_eq!(parsed.next().unwrap().ok().unwrap().lookup("x").unwrap(), + &Value::U64(41)); + assert_eq!(parsed.next().unwrap().ok().unwrap().lookup("x").unwrap(), + &Value::U64(42)); + assert!(parsed.next().is_none()); +} + +#[test] +fn test_json_stream_trailing_whitespaces() { + let stream = "{\"x\":42} \t\n".to_string(); + let mut parsed:JSONStream = JSONStream::new( + stream.as_bytes().iter().map(|byte| Ok(*byte))); + assert_eq!(parsed.next().unwrap().ok().unwrap().lookup("x").unwrap(), + &Value::U64(42)); + assert!(parsed.next().is_none()); +} + +#[test] +fn test_json_stream_truncated() { + let stream = "{\"x\":40}\n{\"x\":".to_string(); + let mut parsed:JSONStream = JSONStream::new( + stream.as_bytes().iter().map(|byte| Ok(*byte))); + assert_eq!(parsed.next().unwrap().ok().unwrap().lookup("x").unwrap(), + &Value::U64(40)); + assert!(parsed.next().unwrap().is_err()); + assert!(parsed.next().is_none()); +} + +#[test] +fn test_json_stream_empty() { + let stream = "".to_string(); + let mut parsed:JSONStream = JSONStream::new( + stream.as_bytes().iter().map(|byte| Ok(*byte))); + assert!(parsed.next().is_none()); +}