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