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