Coverage Report

Created: 2026-02-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}