1use std::borrow::Cow;
4
5use serde_json::{Map, Value};
6
7use crate::{ext::cmp, types::JsonType};
8
9use super::{Json, JsonArrayAccess, JsonNode, JsonObjectAccess};
10
11pub struct SerdeJson;
12
13impl Json for SerdeJson {
14 type Node<'a> = &'a Value;
15 type PreparedKey = String;
16
17 fn prepare_key(key: &str) -> String {
18 key.to_owned()
19 }
20}
21
22impl<'a> JsonNode<'a, SerdeJson> for &'a Value {
23 type Object = &'a Map<String, Value>;
24 type Array = &'a [Value];
25
26 fn as_object(&self) -> Option<&'a Map<String, Value>> {
27 match self {
28 Value::Object(members) => Some(members),
29 _ => None,
30 }
31 }
32
33 fn as_array(&self) -> Option<&'a [Value]> {
34 match self {
35 Value::Array(items) => Some(items),
36 _ => None,
37 }
38 }
39
40 fn as_string(&self) -> Option<Cow<'a, str>> {
41 match self {
42 Value::String(string) => Some(Cow::Borrowed(string)),
43 _ => None,
44 }
45 }
46
47 fn as_number(&self) -> Option<Cow<'a, serde_json::Number>> {
48 match self {
49 Value::Number(number) => Some(Cow::Borrowed(number)),
50 _ => None,
51 }
52 }
53
54 fn as_boolean(&self) -> Option<bool> {
55 match self {
56 Value::Bool(boolean) => Some(*boolean),
57 _ => None,
58 }
59 }
60
61 fn is_null(&self) -> bool {
62 matches!(self, Value::Null)
63 }
64
65 fn json_type(&self) -> JsonType {
66 match self {
67 Value::Null => JsonType::Null,
68 Value::Bool(_) => JsonType::Boolean,
69 Value::Number(_) => JsonType::Number,
70 Value::String(_) => JsonType::String,
71 Value::Array(_) => JsonType::Array,
72 Value::Object(_) => JsonType::Object,
73 }
74 }
75
76 fn string_length(&self) -> Option<u64> {
77 match self {
78 Value::String(string) => Some(bytecount::num_chars(string.as_bytes()) as u64),
80 _ => None,
81 }
82 }
83
84 fn equals_value(&self, expected: &Value) -> bool {
85 cmp::equal(self, expected)
86 }
87
88 fn to_value(&self) -> Cow<'a, Value> {
89 Cow::Borrowed(self)
90 }
91
92 fn cache_key(&self) -> Option<usize> {
93 Some(std::ptr::from_ref::<Value>(self) as usize)
94 }
95}
96
97pub struct SerdeMembersIter<'a>(serde_json::map::Iter<'a>);
98
99impl<'a> Iterator for SerdeMembersIter<'a> {
100 type Item = (&'a str, &'a Value);
101
102 fn next(&mut self) -> Option<Self::Item> {
103 self.0.next().map(|(key, value)| (key.as_str(), value))
104 }
105}
106
107impl<'a> JsonObjectAccess<'a, SerdeJson> for &'a Map<String, Value> {
108 type Node = &'a Value;
109 type MemberName = &'a str;
110 type MembersIter = SerdeMembersIter<'a>;
111
112 fn len(&self) -> usize {
113 Map::len(self)
114 }
115
116 fn get(&self, key: &String) -> Option<&'a Value> {
117 (*self).get(key.as_str())
118 }
119
120 fn members(&self) -> SerdeMembersIter<'a> {
121 SerdeMembersIter((*self).iter())
122 }
123}
124
125impl<'a> JsonArrayAccess<'a, SerdeJson> for &'a [Value] {
126 type Node = &'a Value;
127 type ElementsIter = std::slice::Iter<'a, Value>;
128
129 fn len(&self) -> usize {
130 <[Value]>::len(self)
131 }
132
133 fn elements(&self) -> std::slice::Iter<'a, Value> {
134 (*self).iter()
135 }
136
137 fn is_unique(&self) -> bool {
138 crate::ext::unique::is_unique(self)
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use std::borrow::Cow;
145
146 use serde_json::{json, Value};
147 use test_case::test_case;
148
149 use super::{
150 super::{Json, JsonArrayAccess, JsonNode, JsonObjectAccess},
151 SerdeJson,
152 };
153 use crate::types::JsonType;
154
155 fn assert_document_accessors<F: Json>(node: &F::Node<'_>) {
158 let object = node.as_object().expect("object");
159
160 let member = |name: &str| object.get(&F::prepare_key(name)).expect("present");
161
162 assert!(member("object").as_object().is_some());
163 assert_eq!(member("array").as_array().expect("array").len(), 3);
164 assert_eq!(member("string").as_string().as_deref(), Some("héllo"));
165 assert_eq!(member("string").json_type(), JsonType::String);
166 assert_eq!(member("string").string_length(), Some(5));
167 assert_eq!(
168 member("integer").as_number().expect("number").as_u64(),
169 Some(42)
170 );
171 assert_eq!(
172 member("float").as_number().expect("number").as_f64(),
173 Some(1.5)
174 );
175 assert_eq!(member("boolean").as_boolean(), Some(true));
176 assert!(member("null").is_null());
177 assert_eq!(member("null").json_type(), JsonType::Null);
178 assert!(object.get(&F::prepare_key("missing")).is_none());
179 }
180
181 #[test]
182 fn accessors_match_value_kinds() {
183 let document = json!({
184 "object": {"a": 1},
185 "array": [1, 2, 3],
186 "string": "héllo",
187 "integer": 42,
188 "float": 1.5,
189 "boolean": true,
190 "null": null
191 });
192 assert_document_accessors::<SerdeJson>(&&document);
193 }
194
195 #[test_case(&json!(1), &json!(1.0), true; "integer equals float")]
196 #[test_case(&json!(1.0), &json!(1), true; "float equals integer")]
197 #[test_case(&json!(1), &json!(2), false; "different integers")]
198 #[test_case(&json!(true), &json!(1), false; "boolean is not a number")]
199 #[test_case(&json!({"a": [1, {"b": 1.0}]}), &json!({"a": [1.0, {"b": 1}]}), true; "nested numeric equality")]
200 #[test_case(&json!({"a": [1, {"b": 1.0}]}), &json!({"a": [1, {"b": 2}]}), false; "nested mismatch")]
201 fn equals_value_follows_json_schema_semantics(left: &Value, right: &Value, expected: bool) {
202 assert_eq!(left.equals_value(right), expected);
203 }
204
205 #[test_case("", 0; "empty")]
206 #[test_case("héllo", 5; "multi-byte")]
207 #[test_case("🦀🦀", 2; "astral plane")]
208 fn string_length_counts_code_points(input: &str, expected: u64) {
209 let value = json!(input);
210 assert_eq!((&value).string_length(), Some(expected));
211 }
212
213 #[test]
214 fn to_value_borrows() {
215 let document = json!({"a": 1});
216 let node = &document;
217 assert!(matches!(node.to_value(), Cow::Borrowed(_)));
218 }
219
220 fn assert_cache_key_stability<F: Json>(node: &F::Node<'_>) {
221 let child = node
222 .as_object()
223 .expect("object")
224 .get(&F::prepare_key("a"))
225 .expect("present");
226 assert_eq!(node.cache_key(), node.cache_key());
227 assert_ne!(node.cache_key(), child.cache_key());
228 }
229
230 #[test]
231 fn cache_key_is_stable_per_node() {
232 let document = json!({"a": {"b": 1}});
233 assert_cache_key_stability::<SerdeJson>(&&document);
234 }
235
236 fn assert_iteration_order<F: Json>(node: &F::Node<'_>) {
237 let object = node.as_object().expect("object");
238 let names: Vec<_> = object
239 .members()
240 .map(|(name, _)| name.as_ref().to_owned())
241 .collect();
242 assert_eq!(names, ["a", "b"]);
243
244 let items = object
245 .get(&F::prepare_key("b"))
246 .expect("present")
247 .as_array()
248 .expect("array");
249 let collected: Vec<Option<u64>> = items
250 .elements()
251 .map(|item| item.as_number().and_then(|number| number.as_u64()))
252 .collect();
253 assert_eq!(collected, [Some(10), Some(20)]);
254 }
255
256 #[test]
257 fn members_and_items_iterate_in_order() {
258 let document = json!({"a": 1, "b": [10, 20]});
259 assert_iteration_order::<SerdeJson>(&&document);
260 }
261}