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}