jzon/value/
mod.rs

1use std::ops::{Index, IndexMut, Deref};
2use std::convert::TryInto;
3use std::{fmt, mem, usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32};
4use std::io::{self, Write};
5
6use crate::{Result, Error};
7use crate::short::Short;
8use crate::number::Number;
9use crate::object::Object;
10use crate::iterators::{ Members, MembersMut, Entries, EntriesMut };
11use crate::codegen::{ Generator, PrettyGenerator, DumpGenerator, WriterGenerator, PrettyWriterGenerator };
12
13mod implements;
14
15// These are convenience macros for converting `f64` to the `$unsigned` type.
16// The macros check that the numbers are representable the target type.
17macro_rules! number_to_unsigned {
18    ($unsigned:ident, $value:expr, $high:ty) => {
19        if $value > $unsigned::MAX as $high {
20            None
21        } else {
22            Some($value as $unsigned)
23        }
24    }
25}
26
27macro_rules! number_to_signed {
28    ($signed:ident, $value:expr, $high:ty) => {
29        if $value < $signed::MIN as $high || $value > $signed::MAX as $high {
30            None
31        } else {
32            Some($value as $signed)
33        }
34    }
35}
36
37#[derive(Debug, Clone)]
38pub enum JsonValue {
39    Null,
40    Short(Short),
41    String(String),
42    Number(Number),
43    Boolean(bool),
44    Object(Object),
45    Array(Vec<JsonValue>),
46}
47
48impl PartialEq for JsonValue {
49    fn eq(&self, other: &Self) -> bool {
50        use self::JsonValue::*;
51        match (self, other) {
52            (&Null, &Null) => true,
53            (&Short(ref a), &Short(ref b)) => a == b,
54            (&String(ref a), &String(ref b)) => a == b,
55            (&Short(ref a), &String(ref b))
56            | (&String(ref b), &Short(ref a)) => a.as_str() == b.as_str(),
57            (&Number(ref a), &Number(ref b)) => a == b,
58            (&Boolean(ref a), &Boolean(ref b)) => a == b,
59            (&Object(ref a), &Object(ref b)) => a == b,
60            (&Array(ref a), &Array(ref b)) => a == b,
61            _ => false,
62        }
63    }
64}
65
66impl Eq for JsonValue {}
67
68/// Implements formatting
69///
70/// ```
71/// # use jzon;
72/// let data = jzon::parse(r#"{"url":"https://github.com/"}"#).unwrap();
73/// println!("{}", data);
74/// println!("{:#}", data);
75/// ```
76impl fmt::Display for JsonValue {
77    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78        if f.alternate() {
79            f.write_str(&self.pretty(4))
80        } else {
81            match *self {
82                JsonValue::Short(ref value)   => value.fmt(f),
83                JsonValue::String(ref value)  => value.fmt(f),
84                JsonValue::Number(ref value)  => value.fmt(f),
85                JsonValue::Boolean(ref value) => value.fmt(f),
86                JsonValue::Null               => f.write_str("null"),
87                _                             => f.write_str(&self.dump())
88            }
89        }
90    }
91}
92
93
94static NULL: JsonValue = JsonValue::Null;
95
96impl JsonValue {
97    /// Create an empty `JsonValue::Object` instance.
98    /// When creating an object with data, consider using the `object!` macro.
99    pub fn new_object() -> JsonValue {
100        JsonValue::Object(Object::new())
101    }
102
103    /// Create an empty `JsonValue::Array` instance.
104    /// When creating array with data, consider using the `array!` macro.
105    pub fn new_array() -> JsonValue {
106        JsonValue::Array(Vec::new())
107    }
108
109    /// Prints out the value as JSON string.
110    pub fn dump(&self) -> String {
111        let mut gen = DumpGenerator::new();
112        gen.write_json(self).expect("Can't fail");
113        gen.consume()
114    }
115
116    /// Pretty prints out the value as JSON string. Takes an argument that's
117    /// number of spaces to indent new blocks with.
118    pub fn pretty(&self, spaces: u16) -> String {
119        let mut gen = PrettyGenerator::new(spaces);
120        gen.write_json(self).expect("Can't fail");
121        gen.consume()
122    }
123
124    /// Writes the JSON as byte stream into an implementor of `std::io::Write`.
125    ///
126    /// This method is deprecated as it will panic on io errors, use `write` instead.
127    #[deprecated(since="0.10.2", note="use `JsonValue::write` instead")]
128    pub fn to_writer<W: Write>(&self, writer: &mut W) {
129        let mut gen = WriterGenerator::new(writer);
130        gen.write_json(self).expect("Deprecated");
131    }
132
133    /// Writes the JSON as byte stream into an implementor of `std::io::Write`.
134    pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
135        let mut gen = WriterGenerator::new(writer);
136        gen.write_json(self)
137    }
138
139    /// Writes the JSON as byte stream into an implementor of `std::io::Write`.
140    pub fn write_pretty<W: Write>(&self, writer: &mut W, spaces: u16) -> io::Result<()> {
141        let mut gen = PrettyWriterGenerator::new(writer, spaces);
142        gen.write_json(self)
143    }
144
145    pub fn is_string(&self) -> bool {
146        match *self {
147            JsonValue::Short(_)  => true,
148            JsonValue::String(_) => true,
149            _                    => false,
150        }
151    }
152
153    pub fn is_number(&self) -> bool {
154        match *self {
155            JsonValue::Number(_) => true,
156            _                    => false,
157        }
158    }
159
160    pub fn is_boolean(&self) -> bool {
161        match *self {
162            JsonValue::Boolean(_) => true,
163            _                     => false
164        }
165    }
166
167    pub fn is_null(&self) -> bool {
168        match *self {
169            JsonValue::Null => true,
170            _               => false,
171        }
172    }
173
174    pub fn is_object(&self) -> bool {
175        match *self {
176            JsonValue::Object(_) => true,
177            _                    => false,
178        }
179    }
180
181    pub fn is_array(&self) -> bool {
182        match *self {
183            JsonValue::Array(_) => true,
184            _                   => false,
185        }
186    }
187
188    /// Checks whether the value is empty. Returns true for:
189    ///
190    /// - empty string (`""`)
191    /// - number `0`
192    /// - boolean `false`
193    /// - null
194    /// - empty array (`array![]`)
195    /// - empty object (`object!{}`)
196    pub fn is_empty(&self) -> bool {
197        match *self {
198            JsonValue::Null               => true,
199            JsonValue::Short(ref value)   => value.is_empty(),
200            JsonValue::String(ref value)  => value.is_empty(),
201            JsonValue::Number(ref value)  => value.is_empty(),
202            JsonValue::Boolean(ref value) => !value,
203            JsonValue::Array(ref value)   => value.is_empty(),
204            JsonValue::Object(ref value)  => value.is_empty(),
205        }
206    }
207
208    pub fn as_str(&self) -> Option<&str> {
209        match *self {
210            JsonValue::Short(ref value)  => Some(value),
211            JsonValue::String(ref value) => Some(value),
212            _                            => None
213        }
214    }
215
216    pub fn as_number(&self) -> Option<Number> {
217        match *self {
218            JsonValue::Number(value) => Some(value),
219            _                        => None
220        }
221    }
222
223    pub fn as_f64(&self) -> Option<f64> {
224        self.as_number().map(|value| value.into())
225    }
226
227    pub fn as_f32(&self) -> Option<f32> {
228        self.as_number().map(|value| value.into())
229    }
230
231    pub fn as_u64(&self) -> Option<u64> {
232        self.as_number().and_then(|value| {
233            value.try_into().ok()
234        })
235    }
236
237    pub fn as_u32(&self) -> Option<u32> {
238        self.as_u64().and_then(|value| number_to_unsigned!(u32, value, u64))
239    }
240
241    pub fn as_u16(&self) -> Option<u16> {
242        self.as_u64().and_then(|value| number_to_unsigned!(u16, value, u64))
243    }
244
245    pub fn as_u8(&self) -> Option<u8> {
246        self.as_u64().and_then(|value| number_to_unsigned!(u8, value, u64))
247    }
248
249    pub fn as_usize(&self) -> Option<usize> {
250        self.as_u64().and_then(|value| number_to_unsigned!(usize, value, u64))
251    }
252
253    pub fn as_i64(&self) -> Option<i64> {
254        self.as_number().and_then(|value| value.try_into().ok())
255    }
256
257    pub fn as_i32(&self) -> Option<i32> {
258        self.as_i64().and_then(|value| number_to_signed!(i32, value, i64))
259    }
260
261    pub fn as_i16(&self) -> Option<i16> {
262        self.as_i64().and_then(|value| number_to_signed!(i16, value, i64))
263    }
264
265    pub fn as_i8(&self) -> Option<i8> {
266        self.as_i64().and_then(|value| number_to_signed!(i8, value, i64))
267    }
268
269    pub fn as_isize(&self) -> Option<isize> {
270        self.as_i64().and_then(|value| number_to_signed!(isize, value, i64))
271    }
272
273    pub fn as_bool(&self) -> Option<bool> {
274        match *self {
275            JsonValue::Boolean(ref value) => Some(*value),
276            _                             => None
277        }
278    }
279
280    pub fn as_object(&self) -> Option<&Object> {
281        if let Self::Object(object) = self {
282            Some(object)
283        } else {
284            None
285        }
286    }
287
288    pub fn as_object_mut(&mut self) -> Option<&mut Object> {
289        if let Self::Object(object) = self {
290            Some(object)
291        } else {
292            None
293        }
294    }
295
296    pub fn as_array(&self) -> Option<&Vec<JsonValue>> {
297        if let Self::Array(array) = self {
298            Some(array)
299        } else {
300            None
301        }
302    }
303
304    pub fn as_array_mut(&mut self) -> Option<&mut Vec<JsonValue>> {
305        if let Self::Array(array) = self {
306            Some(array)
307        } else {
308            None
309        }
310    }
311
312    /// If `self` is a `JsonValue::Object`, then this looks up an entry by its `key` in the object.
313    ///
314    /// If `self` is not a `JsonValue::Object`, then this method returns `None`.
315    pub fn get(&self, key: &str) -> Option<&JsonValue> {
316        if let Self::Object(object) = self {
317            object.get(key)
318        } else {
319            None
320        }
321    }
322
323    /// If `self` is a `JsonValue::Object`, then this looks up an entry by its `key` in the object.
324    ///
325    /// If `self` is not a `JsonValue::Object`, then this method returns `None`.
326    pub fn get_mut(&mut self, key: &str) -> Option<&mut JsonValue> {
327        if let Self::Object(object) = self {
328            object.get_mut(key)
329        } else {
330            None
331        }
332    }
333
334    /// Obtain an integer at a fixed decimal point. This is useful for
335    /// converting monetary values and doing arithmetic on them without
336    /// rounding errors introduced by floating point operations.
337    ///
338    /// Will return `None` if `Number` called on a value that's not a number,
339    /// or if the number is negative or a NaN.
340    ///
341    /// ```
342    /// # use jzon::JsonValue;
343    /// let price_a = JsonValue::from(5.99);
344    /// let price_b = JsonValue::from(7);
345    /// let price_c = JsonValue::from(10.2);
346    ///
347    /// assert_eq!(price_a.as_fixed_point_u64(2), Some(599));
348    /// assert_eq!(price_b.as_fixed_point_u64(2), Some(700));
349    /// assert_eq!(price_c.as_fixed_point_u64(2), Some(1020));
350    /// ```
351    pub fn as_fixed_point_u64(&self, point: u16) -> Option<u64> {
352        match *self {
353            JsonValue::Number(ref value) => value.as_fixed_point_u64(point),
354            _                            => None
355        }
356    }
357
358    /// Analog to `as_fixed_point_u64`, except returning a signed
359    /// `i64`, properly handling negative numbers.
360    ///
361    /// ```
362    /// # use jzon::JsonValue;
363    /// let balance_a = JsonValue::from(-1.49);
364    /// let balance_b = JsonValue::from(42);
365    ///
366    /// assert_eq!(balance_a.as_fixed_point_i64(2), Some(-149));
367    /// assert_eq!(balance_b.as_fixed_point_i64(2), Some(4200));
368    /// ```
369    pub fn as_fixed_point_i64(&self, point: u16) -> Option<i64> {
370        match *self {
371            JsonValue::Number(ref value) => value.as_fixed_point_i64(point),
372            _                            => None
373        }
374    }
375
376    /// Take over the ownership of the value, leaving `Null` in it's place.
377    ///
378    /// ## Example
379    ///
380    /// ```
381    /// # #[macro_use] extern crate jzon;
382    /// # fn main() {
383    /// let mut data = array!["Foo", 42];
384    ///
385    /// let first = data[0].take();
386    /// let second = data[1].take();
387    ///
388    /// assert!(first == "Foo");
389    /// assert!(second == 42);
390    ///
391    /// assert!(data[0].is_null());
392    /// assert!(data[1].is_null());
393    /// # }
394    /// ```
395    pub fn take(&mut self) -> JsonValue {
396        mem::replace(self, JsonValue::Null)
397    }
398
399    /// Checks that self is a string, returns an owned Rust `String`, leaving
400    /// `Null` in it's place.
401    ///
402    /// - If the contained string is already a heap allocated `String`, then
403    /// the ownership is moved without any heap allocation.
404    ///
405    /// - If the contained string is a `Short`, this will perform a heap
406    /// allocation to convert the types for you.
407    ///
408    /// ## Example
409    ///
410    /// ```
411    /// # #[macro_use] extern crate jzon;
412    /// # fn main() {
413    /// let mut data = array!["Hello", "World"];
414    ///
415    /// let owned = data[0].take_string().expect("Should be a string");
416    ///
417    /// assert_eq!(owned, "Hello");
418    /// assert!(data[0].is_null());
419    /// # }
420    /// ```
421    pub fn take_string(&mut self) -> Option<String> {
422        let mut placeholder = JsonValue::Null;
423
424        mem::swap(self, &mut placeholder);
425
426        match placeholder {
427            JsonValue::Short(short)   => return Some(short.into()),
428            JsonValue::String(string) => return Some(string),
429
430            // Not a string? Swap the original value back in place!
431            _ => mem::swap(self, &mut placeholder)
432        }
433
434        None
435    }
436
437    /// Works on `JsonValue::Array` - pushes a new value to the array.
438    pub fn push<T>(&mut self, value: T) -> Result<()>
439    where T: Into<JsonValue> {
440        match *self {
441            JsonValue::Array(ref mut vec) => {
442                vec.push(value.into());
443                Ok(())
444            },
445            _ => Err(Error::wrong_type("Array"))
446        }
447    }
448
449    /// Works on `JsonValue::Array` - remove and return last element from
450    /// an array. On failure returns a null.
451    pub fn pop(&mut self) -> JsonValue {
452        match *self {
453            JsonValue::Array(ref mut vec) => {
454                vec.pop().unwrap_or(JsonValue::Null)
455            },
456            _ => JsonValue::Null
457        }
458    }
459
460    /// Works on `JsonValue::Array` - checks if the array contains a value
461    pub fn contains<T>(&self, item: T) -> bool where T: PartialEq<JsonValue> {
462        match *self {
463            JsonValue::Array(ref vec) => vec.iter().any(|member| item == *member),
464            _                         => false
465        }
466    }
467
468    /// Works on `JsonValue::Object` - checks if the object has a key
469    pub fn has_key(&self, key: &str) -> bool {
470        match *self {
471            JsonValue::Object(ref object) => object.get(key).is_some(),
472            _                             => false
473        }
474    }
475
476    /// Returns length of array or object (number of keys), defaults to `0` for
477    /// other types.
478    pub fn len(&self) -> usize {
479        match *self {
480            JsonValue::Array(ref vec) => {
481                vec.len()
482            },
483            JsonValue::Object(ref object) => {
484                object.len()
485            },
486            _ => 0
487        }
488    }
489
490    /// Works on `JsonValue::Array` - returns an iterator over members.
491    /// Will return an empty iterator if called on non-array types.
492    /// ## Example
493    /// ```
494    /// # use jzon::JsonValue;
495    /// # #[macro_use] use jzon::array;
496    /// let animals = array!["Cat", "Dog", "Snail"];
497    /// let mut animals_with_letter_a = Vec::new();
498    /// for animal in animals.members() {
499    ///     if animal.as_str().unwrap().contains('a') {
500    ///         animals_with_letter_a.push(animal);
501    ///     }
502    /// }
503    /// assert_eq!(animals_with_letter_a, vec!["Cat", "Snail"]);
504    /// ```
505    pub fn members(&self) -> Members {
506        match *self {
507            JsonValue::Array(ref vec) => {
508                vec.iter()
509            },
510            _ => [].iter()
511        }
512    }
513
514    /// Works on `JsonValue::Array` - returns a mutable iterator over members.
515    /// Will return an empty iterator if called on non-array types.
516    pub fn members_mut(&mut self) -> MembersMut {
517        match *self {
518            JsonValue::Array(ref mut vec) => {
519                vec.iter_mut()
520            },
521            _ => [].iter_mut()
522        }
523    }
524
525    /// Works on `JsonValue::Object` - returns an iterator over key value pairs.
526    /// Will return an empty iterator if called on non-object types.
527    /// ## Example
528    /// ```
529    /// # use jzon::JsonValue;
530    /// let heights = jzon::parse(r#"
531    /// {
532    ///     "Alice": 1.42,
533    ///     "Bob": 1.6,
534    ///     "Carlos": 2.1
535    /// }
536    /// "#).unwrap();
537    /// let mut total_height = 0.0;
538    /// let mut names_with_o: Vec<&str> = Vec::new();
539    /// for (name, height) in heights.entries() {
540    ///     total_height += height.as_f64().unwrap();
541    ///     if name.contains('o') {
542    ///         names_with_o.push(name);
543    ///     }
544    /// }
545    /// assert_eq!(total_height, 5.12);
546    /// assert_eq!(names_with_o, vec!["Bob", "Carlos"]);
547    /// ```
548    pub fn entries(&self) -> Entries {
549        match *self {
550            JsonValue::Object(ref object) => {
551                object.iter()
552            },
553            _ => Entries::empty()
554        }
555    }
556
557    /// Works on `JsonValue::Object` - returns a mutable iterator over
558    /// key value pairs.
559    /// Will return an empty iterator if called on non-object types.
560    pub fn entries_mut(&mut self) -> EntriesMut {
561        match *self {
562            JsonValue::Object(ref mut object) => {
563                object.iter_mut()
564            },
565            _ => EntriesMut::empty()
566        }
567    }
568
569    /// Works on `JsonValue::Object` - inserts a new entry, or override an existing
570    /// one into the object. Note that `key` has to be a `&str` slice and not an owned
571    /// `String`. The internals of `Object` will handle the heap allocation of the key
572    /// if needed for better performance.
573    pub fn insert<T>(&mut self, key: &str, value: T) -> Result<()>
574    where T: Into<JsonValue> {
575        match *self {
576            JsonValue::Object(ref mut object) => {
577                object.insert(key, value.into());
578                Ok(())
579            },
580            _ => Err(Error::wrong_type("Object"))
581        }
582    }
583
584    /// Works on `JsonValue::Object` - remove a key and return the value it held.
585    /// If the key was not present, the method is called on anything but an
586    /// object, it will return a null.
587    pub fn remove(&mut self, key: &str) -> JsonValue {
588        match *self {
589            JsonValue::Object(ref mut object) => {
590                object.remove(key).unwrap_or(JsonValue::Null)
591            },
592            _ => JsonValue::Null
593        }
594    }
595
596    /// Works on `JsonValue::Array` - remove an entry and return the value it held.
597    /// If the method is called on anything but an object or if the index is out of bounds, it
598    /// will return `JsonValue::Null`.
599    pub fn array_remove(&mut self, index: usize) -> JsonValue {
600        match *self {
601            JsonValue::Array(ref mut vec) => {
602                if index < vec.len() {
603                    vec.remove(index)
604                } else {
605                    JsonValue::Null
606                }
607            },
608            _ => JsonValue::Null
609        }
610    }
611
612    /// When called on an array or an object, will wipe them clean. When called
613    /// on a string will clear the string. Numbers and booleans become null.
614    pub fn clear(&mut self) {
615        match *self {
616            JsonValue::String(ref mut string) => string.clear(),
617            JsonValue::Object(ref mut object) => object.clear(),
618            JsonValue::Array(ref mut vec)     => vec.clear(),
619            _                                 => *self = JsonValue::Null,
620        }
621    }
622}
623
624/// Implements indexing by `usize` to easily access array members:
625///
626/// ## Example
627///
628/// ```
629/// # use jzon::JsonValue;
630/// let mut array = JsonValue::new_array();
631///
632/// array.push("foo");
633///
634/// assert!(array[0] == "foo");
635/// ```
636impl Index<usize> for JsonValue {
637    type Output = JsonValue;
638
639    fn index(&self, index: usize) -> &JsonValue {
640        match *self {
641            JsonValue::Array(ref vec) => vec.get(index).unwrap_or(&NULL),
642            _ => &NULL
643        }
644    }
645}
646
647/// Implements mutable indexing by `usize` to easily modify array members:
648///
649/// ## Example
650///
651/// ```
652/// # #[macro_use]
653/// # extern crate jzon;
654/// #
655/// # fn main() {
656/// let mut array = array!["foo", 3.14];
657///
658/// array[1] = "bar".into();
659///
660/// assert!(array[1] == "bar");
661/// # }
662/// ```
663impl IndexMut<usize> for JsonValue {
664    fn index_mut(&mut self, index: usize) -> &mut JsonValue {
665        match *self {
666            JsonValue::Array(ref mut vec) => {
667                let in_bounds = index < vec.len();
668
669                if in_bounds {
670                    &mut vec[index]
671                } else {
672                    vec.push(JsonValue::Null);
673                    vec.last_mut().unwrap()
674                }
675            }
676            _ => {
677                *self = JsonValue::new_array();
678                self.push(JsonValue::Null).unwrap();
679                self.index_mut(index)
680            }
681        }
682    }
683}
684
685/// Implements indexing by `&str` to easily access object members:
686///
687/// ## Example
688///
689/// ```
690/// # #[macro_use]
691/// # extern crate jzon;
692/// #
693/// # fn main() {
694/// let object = object!{
695///     foo: "bar"
696/// };
697///
698/// assert!(object["foo"] == "bar");
699/// # }
700/// ```
701impl<'a> Index<&'a str> for JsonValue {
702    type Output = JsonValue;
703
704    fn index(&self, index: &str) -> &JsonValue {
705        match *self {
706            JsonValue::Object(ref object) => &object[index],
707            _ => &NULL
708        }
709    }
710}
711
712impl Index<String> for JsonValue {
713    type Output = JsonValue;
714
715    fn index(&self, index: String) -> &JsonValue {
716        self.index(index.deref())
717    }
718}
719
720impl<'a> Index<&'a String> for JsonValue {
721    type Output = JsonValue;
722
723    fn index(&self, index: &String) -> &JsonValue {
724        self.index(index.deref())
725    }
726}
727
728/// Implements mutable indexing by `&str` to easily modify object members:
729///
730/// ## Example
731///
732/// ```
733/// # #[macro_use]
734/// # extern crate jzon;
735/// #
736/// # fn main() {
737/// let mut object = object!{};
738///
739/// object["foo"] = 42.into();
740///
741/// assert!(object["foo"] == 42);
742/// # }
743/// ```
744impl<'a> IndexMut<&'a str> for JsonValue {
745    fn index_mut(&mut self, index: &str) -> &mut JsonValue {
746        match *self {
747            JsonValue::Object(ref mut object) => {
748                &mut object[index]
749            },
750            _ => {
751                *self = JsonValue::new_object();
752                self.index_mut(index)
753            }
754        }
755    }
756}
757
758impl IndexMut<String> for JsonValue {
759    fn index_mut(&mut self, index: String) -> &mut JsonValue {
760        self.index_mut(index.deref())
761    }
762}
763
764impl<'a> IndexMut<&'a String> for JsonValue {
765    fn index_mut(&mut self, index: &String) -> &mut JsonValue {
766        self.index_mut(index.deref())
767    }
768}