serde_json/value/
index.rs

1use std::fmt;
2use std::ops;
3
4use super::Value;
5use map::Map;
6
7/// A type that can be used to index into a `serde_json::Value`.
8///
9/// The [`get`] and [`get_mut`] methods of `Value` accept any type that
10/// implements `Index`, as does the [square-bracket indexing operator]. This
11/// trait is implemented for strings which are used as the index into a JSON
12/// map, and for `usize` which is used as the index into a JSON array.
13///
14/// [`get`]: ../enum.Value.html#method.get
15/// [`get_mut`]: ../enum.Value.html#method.get_mut
16/// [square-bracket indexing operator]: ../enum.Value.html#impl-Index%3CI%3E
17///
18/// This trait is sealed and cannot be implemented for types outside of
19/// `serde_json`.
20///
21/// # Examples
22///
23/// ```edition2018
24/// # use serde_json::json;
25/// #
26/// let data = json!({ "inner": [1, 2, 3] });
27///
28/// // Data is a JSON map so it can be indexed with a string.
29/// let inner = &data["inner"];
30///
31/// // Inner is a JSON array so it can be indexed with an integer.
32/// let first = &inner[0];
33///
34/// assert_eq!(first, 1);
35/// ```
36pub trait Index: private::Sealed {
37    /// Return None if the key is not already in the array or object.
38    #[doc(hidden)]
39    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
40
41    /// Return None if the key is not already in the array or object.
42    #[doc(hidden)]
43    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
44
45    /// Panic if array index out of bounds. If key is not already in the object,
46    /// insert it with a value of null. Panic if Value is a type that cannot be
47    /// indexed into, except if Value is null then it can be treated as an empty
48    /// object.
49    #[doc(hidden)]
50    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
51}
52
53impl Index for usize {
54    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
55        match *v {
56            Value::Array(ref vec) => vec.get(*self),
57            _ => None,
58        }
59    }
60    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
61        match *v {
62            Value::Array(ref mut vec) => vec.get_mut(*self),
63            _ => None,
64        }
65    }
66    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
67        match *v {
68            Value::Array(ref mut vec) => {
69                let len = vec.len();
70                vec.get_mut(*self).unwrap_or_else(|| {
71                    panic!(
72                        "cannot access index {} of JSON array of length {}",
73                        self, len
74                    )
75                })
76            }
77            _ => panic!("cannot access index {} of JSON {}", self, Type(v)),
78        }
79    }
80}
81
82impl Index for str {
83    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
84        match *v {
85            Value::Object(ref map) => map.get(self),
86            _ => None,
87        }
88    }
89    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
90        match *v {
91            Value::Object(ref mut map) => map.get_mut(self),
92            _ => None,
93        }
94    }
95    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
96        if let Value::Null = *v {
97            *v = Value::Object(Map::new());
98        }
99        match *v {
100            Value::Object(ref mut map) => map.entry(self.to_owned()).or_insert(Value::Null),
101            _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
102        }
103    }
104}
105
106impl Index for String {
107    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
108        self[..].index_into(v)
109    }
110    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
111        self[..].index_into_mut(v)
112    }
113    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
114        self[..].index_or_insert(v)
115    }
116}
117
118impl<'a, T: ?Sized> Index for &'a T
119where
120    T: Index,
121{
122    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
123        (**self).index_into(v)
124    }
125    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
126        (**self).index_into_mut(v)
127    }
128    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
129        (**self).index_or_insert(v)
130    }
131}
132
133// Prevent users from implementing the Index trait.
134mod private {
135    pub trait Sealed {}
136    impl Sealed for usize {}
137    impl Sealed for str {}
138    impl Sealed for String {}
139    impl<'a, T: ?Sized> Sealed for &'a T where T: Sealed {}
140}
141
142/// Used in panic messages.
143struct Type<'a>(&'a Value);
144
145impl<'a> fmt::Display for Type<'a> {
146    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
147        match *self.0 {
148            Value::Null => formatter.write_str("null"),
149            Value::Bool(_) => formatter.write_str("boolean"),
150            Value::Number(_) => formatter.write_str("number"),
151            Value::String(_) => formatter.write_str("string"),
152            Value::Array(_) => formatter.write_str("array"),
153            Value::Object(_) => formatter.write_str("object"),
154        }
155    }
156}
157
158// The usual semantics of Index is to panic on invalid indexing.
159//
160// That said, the usual semantics are for things like Vec and BTreeMap which
161// have different use cases than Value. If you are working with a Vec, you know
162// that you are working with a Vec and you can get the len of the Vec and make
163// sure your indices are within bounds. The Value use cases are more
164// loosey-goosey. You got some JSON from an endpoint and you want to pull values
165// out of it. Outside of this Index impl, you already have the option of using
166// value.as_array() and working with the Vec directly, or matching on
167// Value::Array and getting the Vec directly. The Index impl means you can skip
168// that and index directly into the thing using a concise syntax. You don't have
169// to check the type, you don't have to check the len, it is all about what you
170// expect the Value to look like.
171//
172// Basically the use cases that would be well served by panicking here are
173// better served by using one of the other approaches: get and get_mut,
174// as_array, or match. The value of this impl is that it adds a way of working
175// with Value that is not well served by the existing approaches: concise and
176// careless and sometimes that is exactly what you want.
177impl<I> ops::Index<I> for Value
178where
179    I: Index,
180{
181    type Output = Value;
182
183    /// Index into a `serde_json::Value` using the syntax `value[0]` or
184    /// `value["k"]`.
185    ///
186    /// Returns `Value::Null` if the type of `self` does not match the type of
187    /// the index, for example if the index is a string and `self` is an array
188    /// or a number. Also returns `Value::Null` if the given key does not exist
189    /// in the map or the given index is not within the bounds of the array.
190    ///
191    /// For retrieving deeply nested values, you should have a look at the
192    /// `Value::pointer` method.
193    ///
194    /// # Examples
195    ///
196    /// ```edition2018
197    /// # use serde_json::json;
198    /// #
199    /// let data = json!({
200    ///     "x": {
201    ///         "y": ["z", "zz"]
202    ///     }
203    /// });
204    ///
205    /// assert_eq!(data["x"]["y"], json!(["z", "zz"]));
206    /// assert_eq!(data["x"]["y"][0], json!("z"));
207    ///
208    /// assert_eq!(data["a"], json!(null)); // returns null for undefined values
209    /// assert_eq!(data["a"]["b"], json!(null)); // does not panic
210    /// ```
211    fn index(&self, index: I) -> &Value {
212        static NULL: Value = Value::Null;
213        index.index_into(self).unwrap_or(&NULL)
214    }
215}
216
217impl<I> ops::IndexMut<I> for Value
218where
219    I: Index,
220{
221    /// Write into a `serde_json::Value` using the syntax `value[0] = ...` or
222    /// `value["k"] = ...`.
223    ///
224    /// If the index is a number, the value must be an array of length bigger
225    /// than the index. Indexing into a value that is not an array or an array
226    /// that is too small will panic.
227    ///
228    /// If the index is a string, the value must be an object or null which is
229    /// treated like an empty object. If the key is not already present in the
230    /// object, it will be inserted with a value of null. Indexing into a value
231    /// that is neither an object nor null will panic.
232    ///
233    /// # Examples
234    ///
235    /// ```edition2018
236    /// # use serde_json::json;
237    /// #
238    /// let mut data = json!({ "x": 0 });
239    ///
240    /// // replace an existing key
241    /// data["x"] = json!(1);
242    ///
243    /// // insert a new key
244    /// data["y"] = json!([false, false, false]);
245    ///
246    /// // replace an array value
247    /// data["y"][0] = json!(true);
248    ///
249    /// // inserted a deeply nested key
250    /// data["a"]["b"]["c"]["d"] = json!(true);
251    ///
252    /// println!("{}", data);
253    /// ```
254    fn index_mut(&mut self, index: I) -> &mut Value {
255        index.index_or_insert(self)
256    }
257}