]>
git.proxmox.com Git - rustc.git/blob - src/vendor/serde_json/src/value/index.rs
1 // Copyright 2017 Serde Developers
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
15 /// A type that can be used to index into a `serde_json::Value`.
17 /// The [`get`] and [`get_mut`] methods of `Value` accept any type that
18 /// implements `Index`, as does the [square-bracket indexing operator]. This
19 /// trait is implemented for strings which are used as the index into a JSON
20 /// map, and for `usize` which is used as the index into a JSON array.
22 /// [`get`]: ../enum.Value.html#method.get
23 /// [`get_mut`]: ../enum.Value.html#method.get_mut
24 /// [square-bracket indexing operator]: ../enum.Value.html#impl-Index%3CI%3E
26 /// This trait is sealed and cannot be implemented for types outside of
33 /// # extern crate serde_json;
36 /// let data = json!({ "inner": [1, 2, 3] });
38 /// // Data is a JSON map so it can be indexed with a string.
39 /// let inner = &data["inner"];
41 /// // Inner is a JSON array so it can be indexed with an integer.
42 /// let first = &inner[0];
44 /// assert_eq!(first, 1);
47 pub trait Index
: private
::Sealed
{
48 /// Return None if the key is not already in the array or object.
50 fn index_into
<'v
>(&self, v
: &'v Value
) -> Option
<&'v Value
>;
52 /// Return None if the key is not already in the array or object.
54 fn index_into_mut
<'v
>(&self, v
: &'v
mut Value
) -> Option
<&'v
mut Value
>;
56 /// Panic if array index out of bounds. If key is not already in the object,
57 /// insert it with a value of null. Panic if Value is a type that cannot be
58 /// indexed into, except if Value is null then it can be treated as an empty
61 fn index_or_insert
<'v
>(&self, v
: &'v
mut Value
) -> &'v
mut Value
;
64 impl Index
for usize {
65 fn index_into
<'v
>(&self, v
: &'v Value
) -> Option
<&'v Value
> {
67 Value
::Array(ref vec
) => vec
.get(*self),
71 fn index_into_mut
<'v
>(&self, v
: &'v
mut Value
) -> Option
<&'v
mut Value
> {
73 Value
::Array(ref mut vec
) => vec
.get_mut(*self),
77 fn index_or_insert
<'v
>(&self, v
: &'v
mut Value
) -> &'v
mut Value
{
79 Value
::Array(ref mut vec
) => {
85 "cannot access index {} of JSON array of length {}",
92 _
=> panic
!("cannot access index {} of JSON {}", self, Type(v
)),
98 fn index_into
<'v
>(&self, v
: &'v Value
) -> Option
<&'v Value
> {
100 Value
::Object(ref map
) => map
.get(self),
104 fn index_into_mut
<'v
>(&self, v
: &'v
mut Value
) -> Option
<&'v
mut Value
> {
106 Value
::Object(ref mut map
) => map
.get_mut(self),
110 fn index_or_insert
<'v
>(&self, v
: &'v
mut Value
) -> &'v
mut Value
{
111 if let Value
::Null
= *v
{
112 let mut map
= Map
::new();
113 map
.insert(self.to_owned(), Value
::Null
);
114 *v
= Value
::Object(map
);
117 Value
::Object(ref mut map
) => {
118 map
.entry(self.to_owned()).or_insert(Value
::Null
)
120 _
=> panic
!("cannot access key {:?} in JSON {}", self, Type(v
)),
125 impl Index
for String
{
126 fn index_into
<'v
>(&self, v
: &'v Value
) -> Option
<&'v Value
> {
127 self[..].index_into(v
)
129 fn index_into_mut
<'v
>(&self, v
: &'v
mut Value
) -> Option
<&'v
mut Value
> {
130 self[..].index_into_mut(v
)
132 fn index_or_insert
<'v
>(&self, v
: &'v
mut Value
) -> &'v
mut Value
{
133 self[..].index_or_insert(v
)
137 impl<'a
, T
: ?Sized
> Index
for &'a T
141 fn index_into
<'v
>(&self, v
: &'v Value
) -> Option
<&'v Value
> {
142 (**self).index_into(v
)
144 fn index_into_mut
<'v
>(&self, v
: &'v
mut Value
) -> Option
<&'v
mut Value
> {
145 (**self).index_into_mut(v
)
147 fn index_or_insert
<'v
>(&self, v
: &'v
mut Value
) -> &'v
mut Value
{
148 (**self).index_or_insert(v
)
152 // Prevent users from implementing the Index trait.
155 impl Sealed
for usize {}
156 impl Sealed
for str {}
157 impl Sealed
for String {}
158 impl<'a
, T
: ?Sized
> Sealed
for &'a T
165 /// Used in panic messages.
166 struct Type
<'a
>(&'a Value
);
168 impl<'a
> fmt
::Display
for Type
<'a
> {
169 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
171 Value
::Null
=> formatter
.write_str("null"),
172 Value
::Bool(_
) => formatter
.write_str("boolean"),
173 Value
::Number(_
) => formatter
.write_str("number"),
174 Value
::String(_
) => formatter
.write_str("string"),
175 Value
::Array(_
) => formatter
.write_str("array"),
176 Value
::Object(_
) => formatter
.write_str("object"),
181 // The usual semantics of Index is to panic on invalid indexing.
183 // That said, the usual semantics are for things like Vec and BTreeMap which
184 // have different use cases than Value. If you are working with a Vec, you know
185 // that you are working with a Vec and you can get the len of the Vec and make
186 // sure your indices are within bounds. The Value use cases are more
187 // loosey-goosey. You got some JSON from an endpoint and you want to pull values
188 // out of it. Outside of this Index impl, you already have the option of using
189 // value.as_array() and working with the Vec directly, or matching on
190 // Value::Array and getting the Vec directly. The Index impl means you can skip
191 // that and index directly into the thing using a concise syntax. You don't have
192 // to check the type, you don't have to check the len, it is all about what you
193 // expect the Value to look like.
195 // Basically the use cases that would be well served by panicking here are
196 // better served by using one of the other approaches: get and get_mut,
197 // as_array, or match. The value of this impl is that it adds a way of working
198 // with Value that is not well served by the existing approaches: concise and
199 // careless and sometimes that is exactly what you want.
200 impl<I
> ops
::Index
<I
> for Value
206 /// Index into a `serde_json::Value` using the syntax `value[0]` or
209 /// Returns `Value::Null` if the type of `self` does not match the type of
210 /// the index, for example if the index is a string and `self` is an array
211 /// or a number. Also returns `Value::Null` if the given key does not exist
212 /// in the map or the given index is not within the bounds of the array.
214 /// For retrieving deeply nested values, you should have a look at the
215 /// `Value::pointer` method.
221 /// # extern crate serde_json;
224 /// let data = json!({
230 /// assert_eq!(data["x"]["y"], json!(["z", "zz"]));
231 /// assert_eq!(data["x"]["y"][0], json!("z"));
233 /// assert_eq!(data["a"], json!(null)); // returns null for undefined values
234 /// assert_eq!(data["a"]["b"], json!(null)); // does not panic
237 fn index(&self, index
: I
) -> &Value
{
238 static NULL
: Value
= Value
::Null
;
239 index
.index_into(self).unwrap_or(&NULL
)
243 impl<I
> ops
::IndexMut
<I
> for Value
247 /// Write into a `serde_json::Value` using the syntax `value[0] = ...` or
248 /// `value["k"] = ...`.
250 /// If the index is a number, the value must be an array of length bigger
251 /// than the index. Indexing into a value that is not an array or an array
252 /// that is too small will panic.
254 /// If the index is a string, the value must be an object or null which is
255 /// treated like an empty object. If the key is not already present in the
256 /// object, it will be inserted with a value of null. Indexing into a value
257 /// that is neither an object nor null will panic.
263 /// # extern crate serde_json;
266 /// let mut data = json!({ "x": 0 });
268 /// // replace an existing key
269 /// data["x"] = json!(1);
271 /// // insert a new key
272 /// data["y"] = json!([false, false, false]);
274 /// // replace an array value
275 /// data["y"][0] = json!(true);
277 /// // inserted a deeply nested key
278 /// data["a"]["b"]["c"]["d"] = json!(true);
280 /// println!("{}", data);
283 fn index_mut(&mut self, index
: I
) -> &mut Value
{
284 index
.index_or_insert(self)