/src/json/src/value/index.rs
Line | Count | Source |
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`]: Value::get |
16 | | /// [`get_mut`]: Value::get_mut |
17 | | /// [square-bracket indexing operator]: Value#impl-Index%3CI%3E-for-Value |
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)] |
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)] |
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)] |
51 | | fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value; |
52 | | } |
53 | | |
54 | | impl Index for usize { |
55 | 0 | fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { |
56 | 0 | match v { |
57 | 0 | Value::Array(vec) => vec.get(*self), |
58 | 0 | _ => None, |
59 | | } |
60 | 0 | } |
61 | 0 | fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { |
62 | 0 | match v { |
63 | 0 | Value::Array(vec) => vec.get_mut(*self), |
64 | 0 | _ => None, |
65 | | } |
66 | 0 | } |
67 | 0 | fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { |
68 | 0 | match v { |
69 | 0 | Value::Array(vec) => { |
70 | 0 | let len = vec.len(); |
71 | 0 | vec.get_mut(*self).unwrap_or_else(|| { |
72 | 0 | panic!( |
73 | 0 | "cannot access index {} of JSON array of length {}", |
74 | | self, len |
75 | | ) |
76 | | }) |
77 | | } |
78 | 0 | _ => panic!("cannot access index {} of JSON {}", self, Type(v)), |
79 | | } |
80 | 0 | } |
81 | | } |
82 | | |
83 | | impl Index for str { |
84 | 0 | fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { |
85 | 0 | match v { |
86 | 0 | Value::Object(map) => map.get(self), |
87 | 0 | _ => None, |
88 | | } |
89 | 0 | } |
90 | 0 | fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { |
91 | 0 | match v { |
92 | 0 | Value::Object(map) => map.get_mut(self), |
93 | 0 | _ => None, |
94 | | } |
95 | 0 | } |
96 | 0 | fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { |
97 | 0 | if let Value::Null = v { |
98 | 0 | *v = Value::Object(Map::new()); |
99 | 0 | } |
100 | 0 | match v { |
101 | 0 | Value::Object(map) => map.entry(self.to_owned()).or_insert(Value::Null), |
102 | 0 | _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)), |
103 | | } |
104 | 0 | } |
105 | | } |
106 | | |
107 | | impl Index for String { |
108 | 0 | fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { |
109 | 0 | self[..].index_into(v) |
110 | 0 | } |
111 | 0 | fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { |
112 | 0 | self[..].index_into_mut(v) |
113 | 0 | } |
114 | 0 | fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { |
115 | 0 | self[..].index_or_insert(v) |
116 | 0 | } |
117 | | } |
118 | | |
119 | | impl<T> Index for &T |
120 | | where |
121 | | T: ?Sized + Index, |
122 | | { |
123 | | fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { |
124 | | (**self).index_into(v) |
125 | | } |
126 | | fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { |
127 | | (**self).index_into_mut(v) |
128 | | } |
129 | | 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<T> Sealed for &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> { |
147 | 0 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
148 | 0 | match *self.0 { |
149 | 0 | Value::Null => formatter.write_str("null"), |
150 | 0 | Value::Bool(_) => formatter.write_str("boolean"), |
151 | 0 | Value::Number(_) => formatter.write_str("number"), |
152 | 0 | Value::String(_) => formatter.write_str("string"), |
153 | 0 | Value::Array(_) => formatter.write_str("array"), |
154 | 0 | Value::Object(_) => formatter.write_str("object"), |
155 | | } |
156 | 0 | } |
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 | | /// ``` |
212 | | 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 | | /// ``` |
255 | | fn index_mut(&mut self, index: I) -> &mut Value { |
256 | | index.index_or_insert(self) |
257 | | } |
258 | | } |