mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-15 01:31:02 +00:00
Factor the json value enum into it's own module
This commit is contained in:
+7
-6
@@ -11,10 +11,10 @@
|
|||||||
use std::collections::TreeMap;
|
use std::collections::TreeMap;
|
||||||
use std::str::StrAllocating;
|
use std::str::StrAllocating;
|
||||||
|
|
||||||
use super::{Json, JsonObject, List, Object, ToJson};
|
use json::value::{Value, List, Object, ToJson};
|
||||||
|
|
||||||
pub struct ListBuilder {
|
pub struct ListBuilder {
|
||||||
list: Vec<Json>,
|
list: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListBuilder {
|
impl ListBuilder {
|
||||||
@@ -22,7 +22,7 @@ impl ListBuilder {
|
|||||||
ListBuilder { list: Vec::new() }
|
ListBuilder { list: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap(self) -> Json {
|
pub fn unwrap(self) -> Value {
|
||||||
List(self.list)
|
List(self.list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ impl ListBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ObjectBuilder {
|
pub struct ObjectBuilder {
|
||||||
object: JsonObject,
|
object: TreeMap<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectBuilder {
|
impl ObjectBuilder {
|
||||||
@@ -52,7 +52,7 @@ impl ObjectBuilder {
|
|||||||
ObjectBuilder { object: TreeMap::new() }
|
ObjectBuilder { object: TreeMap::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap(self) -> Json {
|
pub fn unwrap(self) -> Value {
|
||||||
Object(self.object)
|
Object(self.object)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,8 @@ impl ObjectBuilder {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::TreeMap;
|
use std::collections::TreeMap;
|
||||||
use json::{List, Integer, Object};
|
|
||||||
|
use json::value::{Integer, List, Object};
|
||||||
use super::{ListBuilder, ObjectBuilder};
|
use super::{ListBuilder, ObjectBuilder};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
+63
-664
@@ -100,9 +100,9 @@ let to_serialize_object = "example of string to serialize";
|
|||||||
let serialized_str: String = json::to_string(&to_serialize_object).unwrap();
|
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.
|
JSON API provide an enum `json::Value` and a trait `ToJson` to serialize
|
||||||
The trait `ToJson` serialize object into a container `json::Json` and the API provide writer
|
object. The trait `ToJson` serialize object into a container `json::Value` and
|
||||||
to serialize them into a stream or a string ...
|
the API provide writer to serialize them into a stream or a string ...
|
||||||
|
|
||||||
When using `ToJson` the `Serialize` trait implementation is not mandatory.
|
When using `ToJson` the `Serialize` trait implementation is not mandatory.
|
||||||
|
|
||||||
@@ -125,17 +125,17 @@ pub struct MyStruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ToJson for MyStruct {
|
impl ToJson for MyStruct {
|
||||||
fn to_json( &self ) -> json::Json {
|
fn to_json( &self ) -> json::Value {
|
||||||
let mut d = TreeMap::new();
|
let mut d = TreeMap::new();
|
||||||
d.insert("attr1".to_string(), self.attr1.to_json());
|
d.insert("attr1".to_string(), self.attr1.to_json());
|
||||||
d.insert("attr2".to_string(), self.attr2.to_json());
|
d.insert("attr2".to_string(), self.attr2.to_json());
|
||||||
json::Object(d)
|
d.to_json()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let test2: MyStruct = MyStruct {attr1: 1, attr2:"test".to_string()};
|
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();
|
let json_str: String = tjson.to_string();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -234,12 +234,12 @@ pub struct TestStruct1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ToJson for TestStruct1 {
|
impl ToJson for TestStruct1 {
|
||||||
fn to_json( &self ) -> json::Json {
|
fn to_json( &self ) -> json::Value {
|
||||||
let mut d = TreeMap::new();
|
let mut d = TreeMap::new();
|
||||||
d.insert("data_int".to_string(), self.data_int.to_json());
|
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_str".to_string(), self.data_str.to_json());
|
||||||
d.insert("data_vector".to_string(), self.data_vector.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_str: "toto".to_string(),
|
||||||
data_vector: vec![2,3,4,5],
|
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();
|
let json_str: String = tjson.to_string().into_string();
|
||||||
|
|
||||||
// Deserialize like before.
|
// Deserialize like before.
|
||||||
@@ -264,11 +264,10 @@ fn main() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use std::char;
|
use std::char;
|
||||||
use std::collections::{HashMap, TreeMap, tree_map};
|
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::f64;
|
use std::f64;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{IoResult, MemWriter, AsRefWriter};
|
use std::io::{IoResult, MemWriter};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::num::{FPNaN, FPInfinite};
|
use std::num::{FPNaN, FPInfinite};
|
||||||
use std::num;
|
use std::num;
|
||||||
@@ -276,481 +275,15 @@ use std::str::ScalarValue;
|
|||||||
use std::str;
|
use std::str;
|
||||||
use std::string;
|
use std::string;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use std::vec;
|
|
||||||
|
|
||||||
use de;
|
use de;
|
||||||
use ser::Serialize;
|
use ser::Serialize;
|
||||||
use ser;
|
use ser;
|
||||||
|
|
||||||
|
pub use json::value::{Value, ToJson};
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
|
pub mod value;
|
||||||
/// 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<Json>;
|
|
||||||
pub type JsonObject = TreeMap<string::String, Json>;
|
|
||||||
|
|
||||||
impl Json {
|
|
||||||
/// Serializes a json value into an io::writer. Uses a single line.
|
|
||||||
pub fn to_writer<W: 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<W: 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<i64> {
|
|
||||||
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<f64> {
|
|
||||||
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<bool> {
|
|
||||||
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<S: ser::Serializer<E>, E> ser::Serialize<S, E> 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<D: de::Deserializer<E>, E> de::Deserialize<D, E> for Json {
|
|
||||||
#[inline]
|
|
||||||
fn deserialize_token(d: &mut D, token: de::Token) -> Result<Json, E> {
|
|
||||||
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<Json> = 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<Json>),
|
|
||||||
JsonDeserializerObjectState(tree_map::MoveEntries<string::String, Json>),
|
|
||||||
JsonDeserializerEndState,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct JsonDeserializer {
|
|
||||||
stack: Vec<JsonDeserializerState>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Result<de::Token, ParserError>> for JsonDeserializer {
|
|
||||||
#[inline]
|
|
||||||
fn next(&mut self) -> Option<Result<de::Token, ParserError>> {
|
|
||||||
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<ParserError> 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<JsonDeserializer, ParserError>
|
|
||||||
>(&mut self, _field: &'static str) -> Result<T, ParserError> {
|
|
||||||
// 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<JsonDeserializer, ParserError>
|
|
||||||
>(&mut self, token: de::Token) -> Result<Option<U>, 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<uint, ParserError> {
|
|
||||||
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("<variant-name>".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])),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The failed expectation of InvalidSyntax
|
/// The failed expectation of InvalidSyntax
|
||||||
#[deriving(Clone, PartialEq, Show)]
|
#[deriving(Clone, PartialEq, Show)]
|
||||||
@@ -1158,8 +691,6 @@ impl<W: Writer> ser::Serializer<io::IoError> for Serializer<W> {
|
|||||||
V: Serialize<Serializer<W>, io::IoError>,
|
V: Serialize<Serializer<W>, io::IoError>,
|
||||||
Iter: Iterator<(K, V)>
|
Iter: Iterator<(K, V)>
|
||||||
>(&mut self, mut iter: Iter) -> IoResult<()> {
|
>(&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("{"));
|
try!(self.wr.write_str("{"));
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for (key, value) in iter {
|
for (key, value) in iter {
|
||||||
@@ -2265,14 +1796,6 @@ pub fn from_str<
|
|||||||
from_iter(s.bytes())
|
from_iter(s.bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a json value from a `Json`.
|
|
||||||
pub fn from_json<
|
|
||||||
T: de::Deserialize<JsonDeserializer, ParserError>
|
|
||||||
>(json: Json) -> Result<T, ParserError> {
|
|
||||||
let mut d = JsonDeserializer::new(json);
|
|
||||||
de::Deserialize::deserialize(&mut d)
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! expect(
|
macro_rules! expect(
|
||||||
($e:expr, Null) => ({
|
($e:expr, Null) => ({
|
||||||
match $e {
|
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<A:ToJson> ToJson for Vec<A> {
|
|
||||||
fn to_json(&self) -> Json { List(self.iter().map(|elt| elt.to_json()).collect()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A:ToJson> ToJson for TreeMap<string::String, A> {
|
|
||||||
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<A:ToJson> ToJson for HashMap<string::String, A> {
|
|
||||||
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<A:ToJson> ToJson for Option<A> {
|
|
||||||
fn to_json(&self) -> Json {
|
|
||||||
match *self {
|
|
||||||
None => Null,
|
|
||||||
Some(ref value) => value.to_json()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::fmt::Show;
|
use std::fmt::Show;
|
||||||
@@ -2441,9 +1823,17 @@ mod tests {
|
|||||||
use std::string;
|
use std::string;
|
||||||
use std::collections::TreeMap;
|
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::{Parser, ParserError, from_str};
|
||||||
use super::{JsonDeserializer, ToJson, from_json};
|
use super::value::{JsonDeserializer, ToJson, from_json};
|
||||||
use super::{
|
use super::{
|
||||||
EOFWhileParsingList,
|
EOFWhileParsingList,
|
||||||
EOFWhileParsingObject,
|
EOFWhileParsingObject,
|
||||||
@@ -2481,7 +1871,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ToJson for Animal {
|
impl ToJson for Animal {
|
||||||
fn to_json(&self) -> Json {
|
fn to_json(&self) -> Value {
|
||||||
match *self {
|
match *self {
|
||||||
Dog => {
|
Dog => {
|
||||||
Object(
|
Object(
|
||||||
@@ -2511,7 +1901,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ToJson for Inner {
|
impl ToJson for Inner {
|
||||||
fn to_json(&self) -> Json {
|
fn to_json(&self) -> Value {
|
||||||
Object(
|
Object(
|
||||||
treemap!(
|
treemap!(
|
||||||
"a".to_string() => self.a.to_json(),
|
"a".to_string() => self.a.to_json(),
|
||||||
@@ -2530,7 +1920,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ToJson for Outer {
|
impl ToJson for Outer {
|
||||||
fn to_json(&self) -> Json {
|
fn to_json(&self) -> Value {
|
||||||
Object(
|
Object(
|
||||||
treemap!(
|
treemap!(
|
||||||
"inner".to_string() => self.inner.to_json()
|
"inner".to_string() => self.inner.to_json()
|
||||||
@@ -2907,7 +2297,7 @@ mod tests {
|
|||||||
let v: T = from_str(s).unwrap();
|
let v: T = from_str(s).unwrap();
|
||||||
assert_eq!(v, *value);
|
assert_eq!(v, *value);
|
||||||
|
|
||||||
let v: Json = from_str(s).unwrap();
|
let v: Value = from_str(s).unwrap();
|
||||||
assert_eq!(v, value.to_json());
|
assert_eq!(v, value.to_json());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2920,7 +2310,7 @@ mod tests {
|
|||||||
assert_eq!(v, *value);
|
assert_eq!(v, *value);
|
||||||
|
|
||||||
// Make sure we can round trip back to `Json`.
|
// 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());
|
assert_eq!(v, value.to_json());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3351,14 +2741,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find(){
|
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());
|
let found_str = json_value.find(&"dog".to_string());
|
||||||
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat");
|
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_path(){
|
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(),
|
let found_str = json_value.find_path(&[&"dog".to_string(),
|
||||||
&"cat".to_string(), &"mouse".to_string()]);
|
&"cat".to_string(), &"mouse".to_string()]);
|
||||||
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese");
|
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese");
|
||||||
@@ -3366,7 +2756,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_search(){
|
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());
|
let found_str = json_value.search(&"mouse".to_string()).and_then(|j| j.as_string());
|
||||||
assert!(found_str.is_some());
|
assert!(found_str.is_some());
|
||||||
assert!(found_str.unwrap() == "cheese");
|
assert!(found_str.unwrap() == "cheese");
|
||||||
@@ -3374,27 +2764,27 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_object() {
|
fn test_is_object() {
|
||||||
let json_value: Json = from_str("{}").unwrap();
|
let json_value: Value = from_str("{}").unwrap();
|
||||||
assert!(json_value.is_object());
|
assert!(json_value.is_object());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_as_object() {
|
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 json_object = json_value.as_object();
|
||||||
let map = TreeMap::<string::String, Json>::new();
|
let map = TreeMap::<string::String, Value>::new();
|
||||||
assert_eq!(json_object, Some(&map));
|
assert_eq!(json_object, Some(&map));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_list() {
|
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());
|
assert!(json_value.is_list());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_as_list() {
|
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 json_list = json_value.as_list();
|
||||||
let expected_length = 3;
|
let expected_length = 3;
|
||||||
assert!(json_list.is_some() && json_list.unwrap().len() == expected_length);
|
assert!(json_list.is_some() && json_list.unwrap().len() == expected_length);
|
||||||
@@ -3402,13 +2792,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_string() {
|
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());
|
assert!(json_value.is_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_as_string() {
|
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 json_str = json_value.as_string();
|
||||||
let expected_str = "dog";
|
let expected_str = "dog";
|
||||||
assert_eq!(json_str, Some(expected_str));
|
assert_eq!(json_str, Some(expected_str));
|
||||||
@@ -3416,52 +2806,52 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_number() {
|
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());
|
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());
|
assert!(json_value.is_number());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_i64() {
|
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());
|
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());
|
assert!(!json_value.is_i64());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_f64() {
|
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());
|
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());
|
assert!(json_value.is_f64());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_as_i64() {
|
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));
|
assert_eq!(json_value.as_i64(), Some(12));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_as_f64() {
|
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));
|
assert_eq!(json_value.as_f64(), Some(12.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_boolean() {
|
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());
|
assert!(json_value.is_boolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_as_boolean() {
|
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 json_bool = json_value.as_boolean();
|
||||||
let expected_bool = false;
|
let expected_bool = false;
|
||||||
assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool);
|
assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool);
|
||||||
@@ -3469,13 +2859,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_null() {
|
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());
|
assert!(json_value.is_null());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_as_null() {
|
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 json_null = json_value.as_null();
|
||||||
let expected_null = ();
|
let expected_null = ();
|
||||||
assert!(json_null.is_some() && json_null.unwrap() == expected_null);
|
assert!(json_null.is_some() && json_null.unwrap() == expected_null);
|
||||||
@@ -3496,7 +2886,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
let bytes = mem_buf.unwrap();
|
let bytes = mem_buf.unwrap();
|
||||||
let json_str = from_utf8(bytes.as_slice()).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]
|
#[test]
|
||||||
fn test_prettyencode_hashmap_with_numeric_key() {
|
fn test_prettyencode_hashmap_with_numeric_key() {
|
||||||
@@ -3512,7 +2902,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
let bytes = mem_buf.unwrap();
|
let bytes = mem_buf.unwrap();
|
||||||
let json_str = from_utf8(bytes.as_slice()).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]
|
#[test]
|
||||||
@@ -3820,7 +3210,16 @@ mod bench {
|
|||||||
use serialize;
|
use serialize;
|
||||||
use test::Bencher;
|
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 super::{Parser, from_str};
|
||||||
use de;
|
use de;
|
||||||
|
|
||||||
@@ -3885,7 +3284,7 @@ mod bench {
|
|||||||
json::List(list)
|
json::List(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serializer_json(count: uint) -> Json {
|
fn serializer_json(count: uint) -> Value {
|
||||||
let mut list = vec!();
|
let mut list = vec!();
|
||||||
for _ in range(0, count) {
|
for _ in range(0, count) {
|
||||||
list.push(Object(treemap!(
|
list.push(Object(treemap!(
|
||||||
|
|||||||
@@ -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<Value>),
|
||||||
|
Object(TreeMap<string::String, Value>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
/// Serializes a json value into an io::writer. Uses a single line.
|
||||||
|
pub fn to_writer<W: 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<W: 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<string::String, Value>> {
|
||||||
|
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<Value>> {
|
||||||
|
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<i64> {
|
||||||
|
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<f64> {
|
||||||
|
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<bool> {
|
||||||
|
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<S: ser::Serializer<E>, E> ser::Serialize<S, E> 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<D: de::Deserializer<E>, E> de::Deserialize<D, E> for Value {
|
||||||
|
#[inline]
|
||||||
|
fn deserialize_token(d: &mut D, token: de::Token) -> Result<Value, E> {
|
||||||
|
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<Value> = 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<Value>),
|
||||||
|
JsonDeserializerObjectState(tree_map::MoveEntries<string::String, Value>),
|
||||||
|
JsonDeserializerEndState,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct JsonDeserializer {
|
||||||
|
stack: Vec<JsonDeserializerState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Result<de::Token, ParserError>> for JsonDeserializer {
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<Result<de::Token, ParserError>> {
|
||||||
|
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<ParserError> 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<JsonDeserializer, ParserError>
|
||||||
|
>(&mut self, _field: &'static str) -> Result<T, ParserError> {
|
||||||
|
// 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<JsonDeserializer, ParserError>
|
||||||
|
>(&mut self, token: de::Token) -> Result<Option<U>, 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<uint, ParserError> {
|
||||||
|
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("<variant-name>".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<JsonDeserializer, ParserError>
|
||||||
|
>(json: Value) -> Result<T, ParserError> {
|
||||||
|
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<A:ToJson> ToJson for Vec<A> {
|
||||||
|
fn to_json(&self) -> Value { List(self.iter().map(|elt| elt.to_json()).collect()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A:ToJson> ToJson for TreeMap<string::String, A> {
|
||||||
|
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<A:ToJson> ToJson for HashMap<string::String, A> {
|
||||||
|
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<A:ToJson> ToJson for Option<A> {
|
||||||
|
fn to_json(&self) -> Value {
|
||||||
|
match *self {
|
||||||
|
None => Null,
|
||||||
|
Some(ref value) => value.to_json()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user