1use Opaque;
2use core;
3use core::errors::Result;
4use format;
5use linked_hash_map::LinkedHashMap;
6use serde_json as json;
7use sir::{FieldSir, Sir};
8use utils::is_datetime;
9
10#[derive(Debug)]
11pub struct Json;
12
13impl format::Format for Json {
14 fn decode(&self, object: &core::Source) -> Result<Sir> {
15 let mut der = json::Deserializer::from_reader(object.read()?).into_iter::<json::Value>();
16
17 let value: Result<json::Value> = der.next()
18 .ok_or_else(|| format!("Expected at least one JSON value").into())
19 .and_then(|v| v.map_err(|e| format!("Bad JSON: {}", e).into()));
20
21 let value = value?;
22 let sir = from_json(&value)?;
23
24 Ok(sir)
25 }
26}
27
28impl format::Object for json::Map<String, json::Value> {
29 type Value = json::Value;
30
31 fn get(&self, key: &str) -> Option<&Self::Value> {
32 self.get(key)
33 }
34}
35
36impl format::Value for json::Value {
37 fn as_object(&self) -> Option<&format::Object<Value = Self>> {
38 match *self {
39 json::Value::Object(ref object) => Some(object as &format::Object<Value = Self>),
40 _ => None,
41 }
42 }
43
44 fn as_str(&self) -> Option<&str> {
45 match *self {
46 json::Value::String(ref string) => Some(string),
47 _ => None,
48 }
49 }
50}
51
52fn from_json(value: &json::Value) -> Result<Sir> {
54 let f = match *value {
55 json::Value::Number(ref number) if number.is_u64() => {
56 let number = number
57 .as_u64()
58 .ok_or_else(|| format!("Expected u64, got: {}", number))?;
59
60 Sir::U64(Opaque::new(vec![number]))
61 }
62 json::Value::Number(ref number) if number.is_i64() => {
63 let number = number
64 .as_i64()
65 .ok_or_else(|| format!("Expected i64, got: {}", number))?;
66
67 Sir::I64(Opaque::new(vec![number]))
68 }
69 json::Value::Number(ref number) => {
70 let number = number
73 .as_f64()
74 .ok_or_else(|| format!("Expected f64, got: {}", number))?;
75
76 let diff = (((number as f32) as f64) - number).abs();
77
78 if diff != 0f64 {
79 Sir::Double
80 } else {
81 Sir::Float
82 }
83 }
84 json::Value::Bool(_) => Sir::Boolean,
85 json::Value::String(ref string) => {
86 if is_datetime(string) {
87 Sir::DateTime(Opaque::new(vec![string.to_string()]))
88 } else {
89 Sir::String(Opaque::new(vec![string.to_string()]))
90 }
91 }
92 json::Value::Null => Sir::Any,
93 json::Value::Array(ref array) => Sir::process_array(&array, from_json)?,
94 json::Value::Object(ref map) => {
95 let mut entries = LinkedHashMap::new();
96
97 for (key, value) in map {
98 let value = from_json(value)?;
99
100 let field = FieldSir {
101 optional: value == Sir::Any,
102 field: value,
103 };
104
105 entries.insert(key.to_string(), field);
106 }
107
108 Sir::Object(entries)
109 }
110 };
111
112 return Ok(f);
113}