diff --git a/src/json/builder.rs b/src/json/builder.rs index d2af7b1c..78d1450a 100644 --- a/src/json/builder.rs +++ b/src/json/builder.rs @@ -11,10 +11,10 @@ use std::collections::TreeMap; use std::str::StrAllocating; -use super::{Json, JsonObject, List, Object, ToJson}; +use json::value::{Value, List, Object, ToJson}; pub struct ListBuilder { - list: Vec, + list: Vec, } impl ListBuilder { @@ -22,7 +22,7 @@ impl ListBuilder { ListBuilder { list: Vec::new() } } - pub fn unwrap(self) -> Json { + pub fn unwrap(self) -> Value { List(self.list) } @@ -44,7 +44,7 @@ impl ListBuilder { } pub struct ObjectBuilder { - object: JsonObject, + object: TreeMap, } impl ObjectBuilder { @@ -52,7 +52,7 @@ impl ObjectBuilder { ObjectBuilder { object: TreeMap::new() } } - pub fn unwrap(self) -> Json { + pub fn unwrap(self) -> Value { Object(self.object) } @@ -76,7 +76,8 @@ impl ObjectBuilder { #[cfg(test)] mod tests { use std::collections::TreeMap; - use json::{List, Integer, Object}; + + use json::value::{Integer, List, Object}; use super::{ListBuilder, ObjectBuilder}; #[test] diff --git a/src/json/mod.rs b/src/json/mod.rs index ccabaa1a..cd3bdc4e 100644 --- a/src/json/mod.rs +++ b/src/json/mod.rs @@ -100,9 +100,9 @@ let to_serialize_object = "example of string to serialize"; let serialized_str: String = json::to_string(&to_serialize_object).unwrap(); ``` -JSON API provide an enum `json::Json` and a trait `ToJson` to serialize object. -The trait `ToJson` serialize object into a container `json::Json` and the API provide writer -to serialize them into a stream or a string ... +JSON API provide an enum `json::Value` and a trait `ToJson` to serialize +object. The trait `ToJson` serialize object into a container `json::Value` and +the API provide writer to serialize them into a stream or a string ... When using `ToJson` the `Serialize` trait implementation is not mandatory. @@ -125,17 +125,17 @@ pub struct MyStruct { } impl ToJson for MyStruct { - fn to_json( &self ) -> json::Json { + fn to_json( &self ) -> json::Value { let mut d = TreeMap::new(); d.insert("attr1".to_string(), self.attr1.to_json()); d.insert("attr2".to_string(), self.attr2.to_json()); - json::Object(d) + d.to_json() } } fn main() { let test2: MyStruct = MyStruct {attr1: 1, attr2:"test".to_string()}; - let tjson: json::Json = test2.to_json(); + let tjson: json::Value = test2.to_json(); let json_str: String = tjson.to_string(); } ``` @@ -234,12 +234,12 @@ pub struct TestStruct1 { } impl ToJson for TestStruct1 { - fn to_json( &self ) -> json::Json { + fn to_json( &self ) -> json::Value { let mut d = TreeMap::new(); d.insert("data_int".to_string(), self.data_int.to_json()); d.insert("data_str".to_string(), self.data_str.to_json()); d.insert("data_vector".to_string(), self.data_vector.to_json()); - json::Object(d) + d.to_json() } } @@ -251,7 +251,7 @@ fn main() { data_str: "toto".to_string(), data_vector: vec![2,3,4,5], }; - let tjson: json::Json = test2.to_json(); + let tjson: json::Value = test2.to_json(); let json_str: String = tjson.to_string().into_string(); // Deserialize like before. @@ -264,11 +264,10 @@ fn main() { */ use std::char; -use std::collections::{HashMap, TreeMap, tree_map}; use std::f32; use std::f64; use std::fmt; -use std::io::{IoResult, MemWriter, AsRefWriter}; +use std::io::{IoResult, MemWriter}; use std::io; use std::num::{FPNaN, FPInfinite}; use std::num; @@ -276,481 +275,15 @@ use std::str::ScalarValue; use std::str; use std::string; use std::vec::Vec; -use std::vec; use de; use ser::Serialize; use ser; +pub use json::value::{Value, ToJson}; + pub mod builder; - -/// Represents a json value -#[deriving(Clone, PartialEq, PartialOrd)] -pub enum Json { - Null, - Boolean(bool), - Integer(i64), - Floating(f64), - String(string::String), - List(JsonList), - Object(JsonObject), -} - -pub type JsonList = Vec; -pub type JsonObject = TreeMap; - -impl Json { - /// Serializes a json value into an io::writer. Uses a single line. - pub fn to_writer(&self, wr: W) -> SerializeResult { - let mut serializer = Serializer::new(wr); - self.serialize(&mut serializer) - } - - /// Serializes a json value into an io::writer. - /// Pretty-prints in a more readable format. - pub fn to_pretty_writer(&self, wr: W) -> SerializeResult { - let mut serializer = PrettySerializer::new(wr); - self.serialize(&mut serializer) - } - - /// Serializes a json value into a string - pub fn to_pretty_string(&self) -> string::String { - let mut wr = MemWriter::new(); - self.to_pretty_writer(wr.by_ref()).unwrap(); - str::from_utf8(wr.unwrap().as_slice()).unwrap().to_string() - } - - /// If the Json value is an Object, returns the value associated with the provided key. - /// Otherwise, returns None. - pub fn find<'a>(&'a self, key: &string::String) -> Option<&'a Json>{ - match self { - &Object(ref map) => map.get(key), - _ => None - } - } - - /// Attempts to get a nested Json Object for each key in `keys`. - /// If any key is found not to exist, find_path will return None. - /// Otherwise, it will return the Json value associated with the final key. - pub fn find_path<'a>(&'a self, keys: &[&string::String]) -> Option<&'a Json>{ - let mut target = self; - for key in keys.iter() { - match target.find(*key) { - Some(t) => { target = t; }, - None => return None - } - } - Some(target) - } - - /// If the Json value is an Object, performs a depth-first search until - /// a value associated with the provided key is found. If no value is found - /// or the Json value is not an Object, returns None. - pub fn search<'a>(&'a self, key: &string::String) -> Option<&'a Json> { - match self { - &Object(ref map) => { - match map.get(key) { - Some(json_value) => Some(json_value), - None => { - let mut value : Option<&'a Json> = None; - for (_, v) in map.iter() { - value = v.search(key); - if value.is_some() { - break; - } - } - value - } - } - }, - _ => None - } - } - - /// Returns true if the Json value is an Object. Returns false otherwise. - pub fn is_object<'a>(&'a self) -> bool { - self.as_object().is_some() - } - - /// If the Json value is an Object, returns the associated TreeMap. - /// Returns None otherwise. - pub fn as_object<'a>(&'a self) -> Option<&'a JsonObject> { - match *self { - Object(ref map) => Some(map), - _ => None - } - } - - /// Returns true if the Json value is a List. Returns false otherwise. - pub fn is_list<'a>(&'a self) -> bool { - self.as_list().is_some() - } - - /// If the Json value is a List, returns the associated vector. - /// Returns None otherwise. - pub fn as_list<'a>(&'a self) -> Option<&'a JsonList> { - match *self { - List(ref list) => Some(list), - _ => None - } - } - - /// Returns true if the Json value is a String. Returns false otherwise. - pub fn is_string<'a>(&'a self) -> bool { - self.as_string().is_some() - } - - /// If the Json value is a String, returns the associated str. - /// Returns None otherwise. - pub fn as_string<'a>(&'a self) -> Option<&'a str> { - match *self { - String(ref s) => Some(s.as_slice()), - _ => None - } - } - - /// Returns true if the Json value is a i64 or f64. Returns false otherwise. - pub fn is_number(&self) -> bool { - match *self { - Integer(_) | Floating(_) => true, - _ => false, - } - } - - /// Returns true if the Json value is a i64. Returns false otherwise. - pub fn is_i64(&self) -> bool { - match *self { - Integer(_) => true, - _ => false, - } - } - - /// Returns true if the Json value is a f64. Returns false otherwise. - pub fn is_f64(&self) -> bool { - match *self { - Floating(_) => true, - _ => false, - } - } - - /// If the Json value is a i64, returns the associated i64. - /// Returns None otherwise. - pub fn as_i64(&self) -> Option { - match *self { - Integer(n) => Some(n), - Floating(n) => Some(n as i64), - _ => None - } - } - - /// If the Json value is a f64, returns the associated f64. - /// Returns None otherwise. - pub fn as_f64(&self) -> Option { - match *self { - Integer(n) => Some(n as f64), - Floating(n) => Some(n), - _ => None - } - } - - /// Returns true if the Json value is a Boolean. Returns false otherwise. - pub fn is_boolean(&self) -> bool { - self.as_boolean().is_some() - } - - /// If the Json value is a Boolean, returns the associated bool. - /// Returns None otherwise. - pub fn as_boolean(&self) -> Option { - match *self { - Boolean(b) => Some(b), - _ => None - } - } - - /// Returns true if the Json value is a Null. Returns false otherwise. - pub fn is_null(&self) -> bool { - self.as_null().is_some() - } - - /// If the Json value is a Null, returns (). - /// Returns None otherwise. - pub fn as_null(&self) -> Option<()> { - match *self { - Null => Some(()), - _ => None - } - } -} - -struct WriterFormatter<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>); - -impl<'a, 'b> Writer for WriterFormatter<'a, 'b> { - fn write(&mut self, buf: &[u8]) -> IoResult<()> { - let WriterFormatter(ref mut f) = *self; - f.write(buf).map_err(|_| io::IoError::last_error()) - } -} - -impl fmt::Show for Json { - /// Serializes a json value into a string - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.to_writer(WriterFormatter(f)).map_err(|_| fmt::WriteError) - } -} - -impl, E> ser::Serialize for Json { - #[inline] - fn serialize(&self, s: &mut S) -> Result<(), E> { - match *self { - Null => { - ().serialize(s) - } - Boolean(v) => { - v.serialize(s) - } - Integer(v) => { - v.serialize(s) - } - Floating(v) => { - v.serialize(s) - } - String(ref v) => { - v.serialize(s) - } - List(ref v) => { - v.serialize(s) - } - Object(ref v) => { - v.serialize(s) - } - } - } -} - -impl, E> de::Deserialize for Json { - #[inline] - fn deserialize_token(d: &mut D, token: de::Token) -> Result { - match token { - de::Null => Ok(Null), - de::Bool(x) => Ok(Boolean(x)), - de::Int(x) => Ok(Integer(x as i64)), - de::I8(x) => Ok(Integer(x as i64)), - de::I16(x) => Ok(Integer(x as i64)), - de::I32(x) => Ok(Integer(x as i64)), - de::I64(x) => Ok(Integer(x)), - de::Uint(x) => Ok(Integer(x as i64)), - de::U8(x) => Ok(Integer(x as i64)), - de::U16(x) => Ok(Integer(x as i64)), - de::U32(x) => Ok(Integer(x as i64)), - de::U64(x) => Ok(Integer(x as i64)), - de::F32(x) => Ok(Floating(x as f64)), - de::F64(x) => Ok(Floating(x)), - de::Char(x) => Ok(String(x.to_string())), - de::Str(x) => Ok(String(x.to_string())), - de::String(x) => Ok(String(x)), - de::Option(false) => Ok(Null), - de::Option(true) => de::Deserialize::deserialize(d), - de::TupleStart(_) | de::SeqStart(_) => { - let list = try!(de::Deserialize::deserialize_token(d, token)); - Ok(List(list)) - } - de::StructStart(_, _) | de::MapStart(_) => { - let object = try!(de::Deserialize::deserialize_token(d, token)); - Ok(Object(object)) - } - de::EnumStart(_, name, len) => { - let token = de::SeqStart(len); - let fields: Vec = try!(de::Deserialize::deserialize_token(d, token)); - let mut object = TreeMap::new(); - object.insert(name.to_string(), List(fields)); - Ok(Object(object)) - } - de::End => Err(d.syntax_error(de::End, [de::EndKind])), - } - } -} - -enum JsonDeserializerState { - JsonDeserializerValueState(Json), - JsonDeserializerListState(vec::MoveItems), - JsonDeserializerObjectState(tree_map::MoveEntries), - JsonDeserializerEndState, -} - -pub struct JsonDeserializer { - stack: Vec, -} - -impl JsonDeserializer { - /// Creates a new deserializer instance for deserializing the specified JSON value. - pub fn new(json: Json) -> JsonDeserializer { - JsonDeserializer { - stack: vec!(JsonDeserializerValueState(json)), - } - } -} - -impl Iterator> for JsonDeserializer { - #[inline] - fn next(&mut self) -> Option> { - loop { - match self.stack.pop() { - Some(JsonDeserializerValueState(value)) => { - let token = match value { - Null => de::Null, - Boolean(x) => de::Bool(x), - Integer(x) => de::I64(x), - Floating(x) => de::F64(x), - String(x) => de::String(x), - List(x) => { - let len = x.len(); - self.stack.push(JsonDeserializerListState(x.into_iter())); - de::SeqStart(len) - } - Object(x) => { - let len = x.len(); - self.stack.push(JsonDeserializerObjectState(x.into_iter())); - de::MapStart(len) - } - }; - - return Some(Ok(token)); - } - Some(JsonDeserializerListState(mut iter)) => { - match iter.next() { - Some(value) => { - self.stack.push(JsonDeserializerListState(iter)); - self.stack.push(JsonDeserializerValueState(value)); - // loop around. - } - None => { - return Some(Ok(de::End)); - } - } - } - Some(JsonDeserializerObjectState(mut iter)) => { - match iter.next() { - Some((key, value)) => { - self.stack.push(JsonDeserializerObjectState(iter)); - self.stack.push(JsonDeserializerValueState(value)); - return Some(Ok(de::String(key))); - } - None => { - return Some(Ok(de::End)); - } - } - } - Some(JsonDeserializerEndState) => { - return Some(Ok(de::End)); - } - None => { return None; } - } - } - } -} - -impl de::Deserializer for JsonDeserializer { - fn end_of_stream_error(&mut self) -> ParserError { - SyntaxError(EOFWhileParsingValue, 0, 0) - } - - fn syntax_error(&mut self, token: de::Token, expected: &[de::TokenKind]) -> ParserError { - SyntaxError(DeserializerError(token, ExpectTokens(expected.to_vec())), 0, 0) - } - - fn unexpected_name_error(&mut self, token: de::Token) -> ParserError { - SyntaxError(DeserializerError(token, ExpectName), 0, 0) - } - - fn conversion_error(&mut self, token: de::Token) -> ParserError { - SyntaxError(DeserializerError(token, ExpectConversion), 0, 0) - } - - #[inline] - fn missing_field< - T: de::Deserialize - >(&mut self, _field: &'static str) -> Result { - // JSON can represent `null` values as a missing value, so this isn't - // necessarily an error. - de::Deserialize::deserialize_token(self, de::Null) - } - - // Special case treating options as a nullable value. - #[inline] - fn expect_option< - U: de::Deserialize - >(&mut self, token: de::Token) -> Result, ParserError> { - match token { - de::Null => Ok(None), - token => { - let value: U = try!(de::Deserialize::deserialize_token(self, token)); - Ok(Some(value)) - } - } - } - - // Special case treating enums as a String or a `{"variant": "...", "fields": [...]}`. - #[inline] - fn expect_enum_start(&mut self, - token: de::Token, - _name: &str, - variants: &[&str]) -> Result { - let variant = match token { - de::MapStart(_) => { - let state = match self.stack.pop() { - Some(state) => state, - None => { panic!("state machine error, state stack empty"); } - }; - - let mut iter = match state { - JsonDeserializerObjectState(iter) => iter, - _ => { panic!("state machine error, expected an object"); } - }; - - let (variant, fields) = match iter.next() { - Some((variant, List(fields))) => (variant, fields), - Some((key, value)) => { - return Err(ExpectedError("List".to_string(), format!("{} => {}", key, value))); - } - None => { return Err(MissingFieldError("".to_string())); } - }; - - // Error out if there are other fields in the enum. - match iter.next() { - Some((key, value)) => { - return Err(ExpectedError("None".to_string(), format!("{} => {}", key, value))); - } - None => { } - } - - self.stack.push(JsonDeserializerEndState); - - for field in fields.into_iter().rev() { - self.stack.push(JsonDeserializerValueState(field)); - } - - variant - } - token => { - return Err(ExpectedError("String or Object".to_string(), - format!("{}", token))) - } - }; - - match variants.iter().position(|v| *v == variant.as_slice()) { - Some(idx) => Ok(idx), - None => Err(UnknownVariantError(variant)), - } - } - - #[inline] - fn expect_struct_start(&mut self, token: de::Token, _name: &str) -> Result<(), ParserError> { - match token { - de::MapStart(_) => Ok(()), - _ => Err(self.syntax_error(token, [de::MapStartKind])), - } - } -} +pub mod value; /// The failed expectation of InvalidSyntax #[deriving(Clone, PartialEq, Show)] @@ -1158,8 +691,6 @@ impl ser::Serializer for Serializer { V: Serialize, io::IoError>, Iter: Iterator<(K, V)> >(&mut self, mut iter: Iter) -> IoResult<()> { - //Warning: WriterFormatter was added to work around - // the stack overflow happening on this line try!(self.wr.write_str("{")); let mut first = true; for (key, value) in iter { @@ -2265,14 +1796,6 @@ pub fn from_str< from_iter(s.bytes()) } -/// Decodes a json value from a `Json`. -pub fn from_json< - T: de::Deserialize ->(json: Json) -> Result { - let mut d = JsonDeserializer::new(json); - de::Deserialize::deserialize(&mut d) -} - macro_rules! expect( ($e:expr, Null) => ({ match $e { @@ -2292,147 +1815,6 @@ macro_rules! expect( }) ) -/// A trait for converting values to JSON -pub trait ToJson { - /// Converts the value of `self` to an instance of JSON - fn to_json(&self) -> Json; -} - -impl ToJson for Json { - fn to_json(&self) -> Json { (*self).clone() } -} - -impl ToJson for int { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for i8 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for i16 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for i32 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for i64 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for uint { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for u8 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for u16 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for u32 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for u64 { - fn to_json(&self) -> Json { Integer(*self as i64) } -} - -impl ToJson for f32 { - fn to_json(&self) -> Json { Floating(*self as f64) } -} - -impl ToJson for f64 { - fn to_json(&self) -> Json { Floating(*self) } -} - -impl ToJson for bool { - fn to_json(&self) -> Json { Boolean(*self) } -} - -impl<'a> ToJson for &'a str { - fn to_json(&self) -> Json { String(self.to_string()) } -} - -impl ToJson for string::String { - fn to_json(&self) -> Json { String((*self).clone()) } -} - -macro_rules! peel_to_json_tuple { - ($name:ident, $($other:ident,)*) => (impl_to_json_tuple!($($other,)*)) -} - -macro_rules! impl_to_json_tuple { - () => { - impl<> ToJson for () { - #[inline] - fn to_json(&self) -> Json { - Null - } - } - }; - ( $($name:ident,)+ ) => { - impl<$($name: ToJson),*> ToJson for ($($name,)*) { - #[inline] - #[allow(non_snake_case)] - fn to_json(&self) -> Json { - // FIXME: how can we count macro args? - let mut len = 0; - $({ let $name = 1; len += $name; })*; - - let ($(ref $name,)*) = *self; - - let mut list = Vec::with_capacity(len); - $( - list.push($name.to_json()); - )* - - List(list) - } - } - peel_to_json_tuple!($($name,)*) - } -} - -impl_to_json_tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } - -impl ToJson for Vec { - fn to_json(&self) -> Json { List(self.iter().map(|elt| elt.to_json()).collect()) } -} - -impl ToJson for TreeMap { - fn to_json(&self) -> Json { - let mut d = TreeMap::new(); - for (key, value) in self.iter() { - d.insert((*key).clone(), value.to_json()); - } - Object(d) - } -} - -impl ToJson for HashMap { - fn to_json(&self) -> Json { - let mut d = TreeMap::new(); - for (key, value) in self.iter() { - d.insert((*key).clone(), value.to_json()); - } - Object(d) - } -} - -impl ToJson for Option { - fn to_json(&self) -> Json { - match *self { - None => Null, - Some(ref value) => value.to_json() - } - } -} - #[cfg(test)] mod tests { use std::fmt::Show; @@ -2441,9 +1823,17 @@ mod tests { use std::string; use std::collections::TreeMap; - use super::{Json, Null, Boolean, Floating, String, List, Object}; + use super::value::{ + Value, + Null, + Boolean, + Floating, + String, + List, + Object, + }; use super::{Parser, ParserError, from_str}; - use super::{JsonDeserializer, ToJson, from_json}; + use super::value::{JsonDeserializer, ToJson, from_json}; use super::{ EOFWhileParsingList, EOFWhileParsingObject, @@ -2481,7 +1871,7 @@ mod tests { } impl ToJson for Animal { - fn to_json(&self) -> Json { + fn to_json(&self) -> Value { match *self { Dog => { Object( @@ -2511,7 +1901,7 @@ mod tests { } impl ToJson for Inner { - fn to_json(&self) -> Json { + fn to_json(&self) -> Value { Object( treemap!( "a".to_string() => self.a.to_json(), @@ -2530,7 +1920,7 @@ mod tests { } impl ToJson for Outer { - fn to_json(&self) -> Json { + fn to_json(&self) -> Value { Object( treemap!( "inner".to_string() => self.inner.to_json() @@ -2907,7 +2297,7 @@ mod tests { let v: T = from_str(s).unwrap(); assert_eq!(v, *value); - let v: Json = from_str(s).unwrap(); + let v: Value = from_str(s).unwrap(); assert_eq!(v, value.to_json()); } } @@ -2920,7 +2310,7 @@ mod tests { assert_eq!(v, *value); // Make sure we can round trip back to `Json`. - let v: Json = from_json(value.to_json()).unwrap(); + let v: Value = from_json(value.to_json()).unwrap(); assert_eq!(v, value.to_json()); } } @@ -3351,14 +2741,14 @@ mod tests { #[test] fn test_find(){ - let json_value: Json = from_str("{\"dog\" : \"cat\"}").unwrap(); + let json_value: Value = from_str("{\"dog\" : \"cat\"}").unwrap(); let found_str = json_value.find(&"dog".to_string()); assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat"); } #[test] fn test_find_path(){ - let json_value: Json = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); + let json_value: Value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); let found_str = json_value.find_path(&[&"dog".to_string(), &"cat".to_string(), &"mouse".to_string()]); assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese"); @@ -3366,7 +2756,7 @@ mod tests { #[test] fn test_search(){ - let json_value: Json = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); + let json_value: Value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); let found_str = json_value.search(&"mouse".to_string()).and_then(|j| j.as_string()); assert!(found_str.is_some()); assert!(found_str.unwrap() == "cheese"); @@ -3374,27 +2764,27 @@ mod tests { #[test] fn test_is_object() { - let json_value: Json = from_str("{}").unwrap(); + let json_value: Value = from_str("{}").unwrap(); assert!(json_value.is_object()); } #[test] fn test_as_object() { - let json_value: Json = from_str("{}").unwrap(); + let json_value: Value = from_str("{}").unwrap(); let json_object = json_value.as_object(); - let map = TreeMap::::new(); + let map = TreeMap::::new(); assert_eq!(json_object, Some(&map)); } #[test] fn test_is_list() { - let json_value: Json = from_str("[1, 2, 3]").unwrap(); + let json_value: Value = from_str("[1, 2, 3]").unwrap(); assert!(json_value.is_list()); } #[test] fn test_as_list() { - let json_value: Json = from_str("[1, 2, 3]").unwrap(); + let json_value: Value = from_str("[1, 2, 3]").unwrap(); let json_list = json_value.as_list(); let expected_length = 3; assert!(json_list.is_some() && json_list.unwrap().len() == expected_length); @@ -3402,13 +2792,13 @@ mod tests { #[test] fn test_is_string() { - let json_value: Json = from_str("\"dog\"").unwrap(); + let json_value: Value = from_str("\"dog\"").unwrap(); assert!(json_value.is_string()); } #[test] fn test_as_string() { - let json_value: Json = from_str("\"dog\"").unwrap(); + let json_value: Value = from_str("\"dog\"").unwrap(); let json_str = json_value.as_string(); let expected_str = "dog"; assert_eq!(json_str, Some(expected_str)); @@ -3416,52 +2806,52 @@ mod tests { #[test] fn test_is_number() { - let json_value: Json = from_str("12").unwrap(); + let json_value: Value = from_str("12").unwrap(); assert!(json_value.is_number()); - let json_value: Json = from_str("12.0").unwrap(); + let json_value: Value = from_str("12.0").unwrap(); assert!(json_value.is_number()); } #[test] fn test_is_i64() { - let json_value: Json = from_str("12").unwrap(); + let json_value: Value = from_str("12").unwrap(); assert!(json_value.is_i64()); - let json_value: Json = from_str("12.0").unwrap(); + let json_value: Value = from_str("12.0").unwrap(); assert!(!json_value.is_i64()); } #[test] fn test_is_f64() { - let json_value: Json = from_str("12").unwrap(); + let json_value: Value = from_str("12").unwrap(); assert!(!json_value.is_f64()); - let json_value: Json = from_str("12.0").unwrap(); + let json_value: Value = from_str("12.0").unwrap(); assert!(json_value.is_f64()); } #[test] fn test_as_i64() { - let json_value: Json = from_str("12").unwrap(); + let json_value: Value = from_str("12").unwrap(); assert_eq!(json_value.as_i64(), Some(12)); } #[test] fn test_as_f64() { - let json_value: Json = from_str("12").unwrap(); + let json_value: Value = from_str("12").unwrap(); assert_eq!(json_value.as_f64(), Some(12.0)); } #[test] fn test_is_boolean() { - let json_value: Json = from_str("false").unwrap(); + let json_value: Value = from_str("false").unwrap(); assert!(json_value.is_boolean()); } #[test] fn test_as_boolean() { - let json_value: Json = from_str("false").unwrap(); + let json_value: Value = from_str("false").unwrap(); let json_bool = json_value.as_boolean(); let expected_bool = false; assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool); @@ -3469,13 +2859,13 @@ mod tests { #[test] fn test_is_null() { - let json_value: Json = from_str("null").unwrap(); + let json_value: Value = from_str("null").unwrap(); assert!(json_value.is_null()); } #[test] fn test_as_null() { - let json_value: Json = from_str("null").unwrap(); + let json_value: Value = from_str("null").unwrap(); let json_null = json_value.as_null(); let expected_null = (); assert!(json_null.is_some() && json_null.unwrap() == expected_null); @@ -3496,7 +2886,7 @@ mod tests { } let bytes = mem_buf.unwrap(); let json_str = from_utf8(bytes.as_slice()).unwrap(); - let _json_value: Json = from_str(json_str).unwrap(); + let _json_value: Value = from_str(json_str).unwrap(); } #[test] fn test_prettyencode_hashmap_with_numeric_key() { @@ -3512,7 +2902,7 @@ mod tests { } let bytes = mem_buf.unwrap(); let json_str = from_utf8(bytes.as_slice()).unwrap(); - let _json_value: Json = from_str(json_str).unwrap(); + let _json_value: Value = from_str(json_str).unwrap(); } #[test] @@ -3820,7 +3210,16 @@ mod bench { use serialize; use test::Bencher; - use super::{Json, Null, Boolean, Integer, Floating, String, List, Object}; + use json::value::{ + Value, + Null, + Boolean, + Integer, + Floating, + String, + List, + Object, + }; use super::{Parser, from_str}; use de; @@ -3885,7 +3284,7 @@ mod bench { json::List(list) } - fn serializer_json(count: uint) -> Json { + fn serializer_json(count: uint) -> Value { let mut list = vec!(); for _ in range(0, count) { list.push(Object(treemap!( diff --git a/src/json/value.rs b/src/json/value.rs new file mode 100644 index 00000000..fc234191 --- /dev/null +++ b/src/json/value.rs @@ -0,0 +1,641 @@ +use std::collections::{HashMap, TreeMap, tree_map}; +use std::fmt; +use std::io::{AsRefWriter, IoResult, MemWriter}; +use std::io; +use std::str; +use std::string; +use std::vec; + +use de; +use ser::Serialize; +use ser; + +use super::PrettySerializer; +use super::Serializer; +use super::SerializeResult; +use super::ParserError; +use super::{ + MissingFieldError, + SyntaxError, + DeserializerError, + ExpectName, + ExpectConversion, + ExpectTokens, + EOFWhileParsingValue, + ExpectedError, + UnknownVariantError, +}; + +/// Represents a JSON value +#[deriving(Clone, PartialEq, PartialOrd)] +pub enum Value { + Null, + Boolean(bool), + Integer(i64), + Floating(f64), + String(string::String), + List(Vec), + Object(TreeMap), +} + +impl Value { + /// Serializes a json value into an io::writer. Uses a single line. + pub fn to_writer(&self, wr: W) -> SerializeResult { + let mut serializer = Serializer::new(wr); + self.serialize(&mut serializer) + } + + /// Serializes a json value into an io::writer. + /// Pretty-prints in a more readable format. + pub fn to_pretty_writer(&self, wr: W) -> SerializeResult { + let mut serializer = PrettySerializer::new(wr); + self.serialize(&mut serializer) + } + + /// Serializes a json value into a string + pub fn to_pretty_string(&self) -> string::String { + let mut wr = MemWriter::new(); + self.to_pretty_writer(wr.by_ref()).unwrap(); + str::from_utf8(wr.unwrap().as_slice()).unwrap().to_string() + } + + /// If the Json value is an Object, returns the value associated with the provided key. + /// Otherwise, returns None. + pub fn find<'a>(&'a self, key: &string::String) -> Option<&'a Value>{ + match self { + &Object(ref map) => map.get(key), + _ => None + } + } + + /// Attempts to get a nested Json Object for each key in `keys`. + /// If any key is found not to exist, find_path will return None. + /// Otherwise, it will return the Json value associated with the final key. + pub fn find_path<'a>(&'a self, keys: &[&string::String]) -> Option<&'a Value>{ + let mut target = self; + for key in keys.iter() { + match target.find(*key) { + Some(t) => { target = t; }, + None => return None + } + } + Some(target) + } + + /// If the Json value is an Object, performs a depth-first search until + /// a value associated with the provided key is found. If no value is found + /// or the Json value is not an Object, returns None. + pub fn search<'a>(&'a self, key: &string::String) -> Option<&'a Value> { + match self { + &Object(ref map) => { + match map.get(key) { + Some(json_value) => Some(json_value), + None => { + let mut value : Option<&'a Value> = None; + for (_, v) in map.iter() { + value = v.search(key); + if value.is_some() { + break; + } + } + value + } + } + }, + _ => None + } + } + + /// Returns true if the Json value is an Object. Returns false otherwise. + pub fn is_object<'a>(&'a self) -> bool { + self.as_object().is_some() + } + + /// If the Json value is an Object, returns the associated TreeMap. + /// Returns None otherwise. + pub fn as_object<'a>(&'a self) -> Option<&'a TreeMap> { + match *self { + Object(ref map) => Some(map), + _ => None + } + } + + /// Returns true if the Json value is a List. Returns false otherwise. + pub fn is_list<'a>(&'a self) -> bool { + self.as_list().is_some() + } + + /// If the Json value is a List, returns the associated vector. + /// Returns None otherwise. + pub fn as_list<'a>(&'a self) -> Option<&'a Vec> { + match *self { + List(ref list) => Some(list), + _ => None + } + } + + /// Returns true if the Json value is a String. Returns false otherwise. + pub fn is_string<'a>(&'a self) -> bool { + self.as_string().is_some() + } + + /// If the Json value is a String, returns the associated str. + /// Returns None otherwise. + pub fn as_string<'a>(&'a self) -> Option<&'a str> { + match *self { + String(ref s) => Some(s.as_slice()), + _ => None + } + } + + /// Returns true if the Json value is a i64 or f64. Returns false otherwise. + pub fn is_number(&self) -> bool { + match *self { + Integer(_) | Floating(_) => true, + _ => false, + } + } + + /// Returns true if the Json value is a i64. Returns false otherwise. + pub fn is_i64(&self) -> bool { + match *self { + Integer(_) => true, + _ => false, + } + } + + /// Returns true if the Json value is a f64. Returns false otherwise. + pub fn is_f64(&self) -> bool { + match *self { + Floating(_) => true, + _ => false, + } + } + + /// If the Json value is a i64, returns the associated i64. + /// Returns None otherwise. + pub fn as_i64(&self) -> Option { + match *self { + Integer(n) => Some(n), + Floating(n) => Some(n as i64), + _ => None + } + } + + /// If the Json value is a f64, returns the associated f64. + /// Returns None otherwise. + pub fn as_f64(&self) -> Option { + match *self { + Integer(n) => Some(n as f64), + Floating(n) => Some(n), + _ => None + } + } + + /// Returns true if the Json value is a Boolean. Returns false otherwise. + pub fn is_boolean(&self) -> bool { + self.as_boolean().is_some() + } + + /// If the Json value is a Boolean, returns the associated bool. + /// Returns None otherwise. + pub fn as_boolean(&self) -> Option { + match *self { + Boolean(b) => Some(b), + _ => None + } + } + + /// Returns true if the Json value is a Null. Returns false otherwise. + pub fn is_null(&self) -> bool { + self.as_null().is_some() + } + + /// If the Json value is a Null, returns (). + /// Returns None otherwise. + pub fn as_null(&self) -> Option<()> { + match *self { + Null => Some(()), + _ => None + } + } +} + +struct WriterFormatter<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>); + +impl<'a, 'b> Writer for WriterFormatter<'a, 'b> { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + let WriterFormatter(ref mut f) = *self; + f.write(buf).map_err(|_| io::IoError::last_error()) + } +} + +impl fmt::Show for Value { + /// Serializes a json value into a string + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.to_writer(WriterFormatter(f)).map_err(|_| fmt::WriteError) + } +} + +impl, E> ser::Serialize for Value { + #[inline] + fn serialize(&self, s: &mut S) -> Result<(), E> { + match *self { + Null => { + ().serialize(s) + } + Boolean(v) => { + v.serialize(s) + } + Integer(v) => { + v.serialize(s) + } + Floating(v) => { + v.serialize(s) + } + String(ref v) => { + v.serialize(s) + } + List(ref v) => { + v.serialize(s) + } + Object(ref v) => { + v.serialize(s) + } + } + } +} + +impl, E> de::Deserialize for Value { + #[inline] + fn deserialize_token(d: &mut D, token: de::Token) -> Result { + match token { + de::Null => Ok(Null), + de::Bool(x) => Ok(Boolean(x)), + de::Int(x) => Ok(Integer(x as i64)), + de::I8(x) => Ok(Integer(x as i64)), + de::I16(x) => Ok(Integer(x as i64)), + de::I32(x) => Ok(Integer(x as i64)), + de::I64(x) => Ok(Integer(x)), + de::Uint(x) => Ok(Integer(x as i64)), + de::U8(x) => Ok(Integer(x as i64)), + de::U16(x) => Ok(Integer(x as i64)), + de::U32(x) => Ok(Integer(x as i64)), + de::U64(x) => Ok(Integer(x as i64)), + de::F32(x) => Ok(Floating(x as f64)), + de::F64(x) => Ok(Floating(x)), + de::Char(x) => Ok(String(x.to_string())), + de::Str(x) => Ok(String(x.to_string())), + de::String(x) => Ok(String(x)), + de::Option(false) => Ok(Null), + de::Option(true) => de::Deserialize::deserialize(d), + de::TupleStart(_) | de::SeqStart(_) => { + let list = try!(de::Deserialize::deserialize_token(d, token)); + Ok(List(list)) + } + de::StructStart(_, _) | de::MapStart(_) => { + let object = try!(de::Deserialize::deserialize_token(d, token)); + Ok(Object(object)) + } + de::EnumStart(_, name, len) => { + let token = de::SeqStart(len); + let fields: Vec = try!(de::Deserialize::deserialize_token(d, token)); + let mut object = TreeMap::new(); + object.insert(name.to_string(), List(fields)); + Ok(Object(object)) + } + de::End => Err(d.syntax_error(de::End, [de::EndKind])), + } + } +} + +enum JsonDeserializerState { + JsonDeserializerValueState(Value), + JsonDeserializerListState(vec::MoveItems), + JsonDeserializerObjectState(tree_map::MoveEntries), + JsonDeserializerEndState, +} + +pub struct JsonDeserializer { + stack: Vec, +} + +impl JsonDeserializer { + /// Creates a new deserializer instance for deserializing the specified JSON value. + pub fn new(json: Value) -> JsonDeserializer { + JsonDeserializer { + stack: vec!(JsonDeserializerValueState(json)), + } + } +} + +impl Iterator> for JsonDeserializer { + #[inline] + fn next(&mut self) -> Option> { + loop { + match self.stack.pop() { + Some(JsonDeserializerValueState(value)) => { + let token = match value { + Null => de::Null, + Boolean(x) => de::Bool(x), + Integer(x) => de::I64(x), + Floating(x) => de::F64(x), + String(x) => de::String(x), + List(x) => { + let len = x.len(); + self.stack.push(JsonDeserializerListState(x.into_iter())); + de::SeqStart(len) + } + Object(x) => { + let len = x.len(); + self.stack.push(JsonDeserializerObjectState(x.into_iter())); + de::MapStart(len) + } + }; + + return Some(Ok(token)); + } + Some(JsonDeserializerListState(mut iter)) => { + match iter.next() { + Some(value) => { + self.stack.push(JsonDeserializerListState(iter)); + self.stack.push(JsonDeserializerValueState(value)); + // loop around. + } + None => { + return Some(Ok(de::End)); + } + } + } + Some(JsonDeserializerObjectState(mut iter)) => { + match iter.next() { + Some((key, value)) => { + self.stack.push(JsonDeserializerObjectState(iter)); + self.stack.push(JsonDeserializerValueState(value)); + return Some(Ok(de::String(key))); + } + None => { + return Some(Ok(de::End)); + } + } + } + Some(JsonDeserializerEndState) => { + return Some(Ok(de::End)); + } + None => { return None; } + } + } + } +} + +impl de::Deserializer for JsonDeserializer { + fn end_of_stream_error(&mut self) -> ParserError { + SyntaxError(EOFWhileParsingValue, 0, 0) + } + + fn syntax_error(&mut self, token: de::Token, expected: &[de::TokenKind]) -> ParserError { + SyntaxError(DeserializerError(token, ExpectTokens(expected.to_vec())), 0, 0) + } + + fn unexpected_name_error(&mut self, token: de::Token) -> ParserError { + SyntaxError(DeserializerError(token, ExpectName), 0, 0) + } + + fn conversion_error(&mut self, token: de::Token) -> ParserError { + SyntaxError(DeserializerError(token, ExpectConversion), 0, 0) + } + + #[inline] + fn missing_field< + T: de::Deserialize + >(&mut self, _field: &'static str) -> Result { + // JSON can represent `null` values as a missing value, so this isn't + // necessarily an error. + de::Deserialize::deserialize_token(self, de::Null) + } + + // Special case treating options as a nullable value. + #[inline] + fn expect_option< + U: de::Deserialize + >(&mut self, token: de::Token) -> Result, ParserError> { + match token { + de::Null => Ok(None), + token => { + let value: U = try!(de::Deserialize::deserialize_token(self, token)); + Ok(Some(value)) + } + } + } + + // Special case treating enums as a String or a `{"variant": "...", "fields": [...]}`. + #[inline] + fn expect_enum_start(&mut self, + token: de::Token, + _name: &str, + variants: &[&str]) -> Result { + let variant = match token { + de::MapStart(_) => { + let state = match self.stack.pop() { + Some(state) => state, + None => { panic!("state machine error, state stack empty"); } + }; + + let mut iter = match state { + JsonDeserializerObjectState(iter) => iter, + _ => { panic!("state machine error, expected an object"); } + }; + + let (variant, fields) = match iter.next() { + Some((variant, List(fields))) => (variant, fields), + Some((key, value)) => { + return Err(ExpectedError("List".to_string(), format!("{} => {}", key, value))); + } + None => { return Err(MissingFieldError("".to_string())); } + }; + + // Error out if there are other fields in the enum. + match iter.next() { + Some((key, value)) => { + return Err(ExpectedError("None".to_string(), format!("{} => {}", key, value))); + } + None => { } + } + + self.stack.push(JsonDeserializerEndState); + + for field in fields.into_iter().rev() { + self.stack.push(JsonDeserializerValueState(field)); + } + + variant + } + token => { + return Err(ExpectedError("String or Object".to_string(), + format!("{}", token))) + } + }; + + match variants.iter().position(|v| *v == variant.as_slice()) { + Some(idx) => Ok(idx), + None => Err(UnknownVariantError(variant)), + } + } + + #[inline] + fn expect_struct_start(&mut self, token: de::Token, _name: &str) -> Result<(), ParserError> { + match token { + de::MapStart(_) => Ok(()), + _ => Err(self.syntax_error(token, [de::MapStartKind])), + } + } +} + +/// Decodes a json value from a `Value`. +pub fn from_json< + T: de::Deserialize +>(json: Value) -> Result { + let mut d = JsonDeserializer::new(json); + de::Deserialize::deserialize(&mut d) +} + +/// A trait for converting values to JSON +pub trait ToJson { + /// Converts the value of `self` to an instance of JSON + fn to_json(&self) -> Value; +} + +impl ToJson for Value { + fn to_json(&self) -> Value { (*self).clone() } +} + +impl ToJson for int { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for i8 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for i16 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for i32 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for i64 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for uint { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for u8 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for u16 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for u32 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for u64 { + fn to_json(&self) -> Value { Integer(*self as i64) } +} + +impl ToJson for f32 { + fn to_json(&self) -> Value { Floating(*self as f64) } +} + +impl ToJson for f64 { + fn to_json(&self) -> Value { Floating(*self) } +} + +impl ToJson for bool { + fn to_json(&self) -> Value { Boolean(*self) } +} + +impl<'a> ToJson for &'a str { + fn to_json(&self) -> Value { String(self.to_string()) } +} + +impl ToJson for string::String { + fn to_json(&self) -> Value { String((*self).clone()) } +} + +macro_rules! peel_to_json_tuple { + ($name:ident, $($other:ident,)*) => (impl_to_json_tuple!($($other,)*)) +} + +macro_rules! impl_to_json_tuple { + () => { + impl<> ToJson for () { + #[inline] + fn to_json(&self) -> Value { + Null + } + } + }; + ( $($name:ident,)+ ) => { + impl<$($name: ToJson),*> ToJson for ($($name,)*) { + #[inline] + #[allow(non_snake_case)] + fn to_json(&self) -> Value { + // FIXME: how can we count macro args? + let mut len = 0; + $({ let $name = 1; len += $name; })*; + + let ($(ref $name,)*) = *self; + + let mut list = Vec::with_capacity(len); + $( + list.push($name.to_json()); + )* + + List(list) + } + } + peel_to_json_tuple!($($name,)*) + } +} + +impl_to_json_tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } + +impl ToJson for Vec { + fn to_json(&self) -> Value { List(self.iter().map(|elt| elt.to_json()).collect()) } +} + +impl ToJson for TreeMap { + fn to_json(&self) -> Value { + let mut d = TreeMap::new(); + for (key, value) in self.iter() { + d.insert((*key).clone(), value.to_json()); + } + Object(d) + } +} + +impl ToJson for HashMap { + fn to_json(&self) -> Value { + let mut d = TreeMap::new(); + for (key, value) in self.iter() { + d.insert((*key).clone(), value.to_json()); + } + Object(d) + } +} + +impl ToJson for Option { + fn to_json(&self) -> Value { + match *self { + None => Null, + Some(ref value) => value.to_json() + } + } +}