1use super::{JsonPointerHandler, JsonPointerItem};
8use crate::json::key::Key;
9use crate::pointer::JsonPointerIter;
10use crate::{Element, Property, Value};
11use std::borrow::Cow;
12use std::collections::HashMap;
13use std::hash::BuildHasher;
14
15impl<'x, P: Property, E: Element> JsonPointerHandler<'x, P, E> for Value<'x, P, E> {
16 fn eval_jptr<'y>(
17 &'y self,
18 mut pointer: JsonPointerIter<'_, P>,
19 results: &mut Vec<Cow<'y, Value<'x, P, E>>>,
20 ) {
21 match pointer.next() {
22 Some(JsonPointerItem::Key(key)) => {
23 if let Value::Object(map) = self
24 && let Some(v) = map.get(key)
25 {
26 v.eval_jptr(pointer, results);
27 }
28 }
29 Some(JsonPointerItem::Number(n)) => match self {
30 Value::Array(values) => {
31 if let Some(v) = values.get(*n as usize) {
32 v.eval_jptr(pointer, results);
33 }
34 }
35 Value::Object(map) => {
36 let n = Key::Owned(n.to_string());
37 if let Some(v) = map.get(&n) {
38 v.eval_jptr(pointer, results);
39 }
40 }
41 _ => {}
42 },
43 Some(JsonPointerItem::Wildcard) => match self {
44 Value::Array(values) => {
45 for v in values {
46 v.eval_jptr(pointer.clone(), results);
47 }
48 }
49 Value::Object(map) => {
50 for v in map.values() {
51 v.eval_jptr(pointer.clone(), results);
52 }
53 }
54 _ => {}
55 },
56 Some(JsonPointerItem::Root) | None => {
57 results.push(Cow::Borrowed(self));
58 }
59 }
60 }
61
62 fn patch_jptr<'y: 'x>(
63 &mut self,
64 mut pointer: JsonPointerIter<'_, P>,
65 value: Value<'y, P, E>,
66 ) -> bool {
67 match pointer.next() {
68 Some(JsonPointerItem::Key(key)) => {
69 if let Value::Object(map) = self {
70 if let Some(pos) = map.0.iter().position(|(k, _)| k == key) {
71 return if pointer.peek().is_some() {
72 map.0[pos].1.patch_jptr(pointer, value)
73 } else {
74 map.0[pos].1 = value;
75 true
76 };
77 } else if pointer.next().is_none() {
78 map.insert_unchecked(key.clone(), value);
79 return true;
80 }
81 }
82 }
83 Some(JsonPointerItem::Number(n)) => match self {
84 Value::Array(values) => {
85 if let Some(item) = values.get_mut(*n as usize) {
86 return if pointer.peek().is_some() {
87 item.patch_jptr(pointer, value)
88 } else {
89 *item = value;
90 true
91 };
92 }
93 }
94 Value::Object(map) => {
95 let n = Key::Owned(n.to_string());
96 if let Some(item) = map.get_mut(&n) {
97 return if pointer.peek().is_some() {
98 item.patch_jptr(pointer, value)
99 } else {
100 *item = value;
101 true
102 };
103 }
104 }
105 _ => {}
106 },
107 Some(JsonPointerItem::Wildcard) | Some(JsonPointerItem::Root) | None => (),
108 }
109
110 false
111 }
112
113 fn to_value<'y>(&'y self) -> Cow<'y, Value<'x, P, E>> {
114 Cow::Borrowed(self)
115 }
116}
117
118impl<'x, P: Property, E: Element, T> JsonPointerHandler<'x, P, E> for Vec<T>
119where
120 T: JsonPointerHandler<'x, P, E> + for<'y> TryFrom<Value<'y, P, E>> + 'static,
121{
122 fn eval_jptr<'y>(
123 &'y self,
124 mut pointer: JsonPointerIter<'_, P>,
125 results: &mut Vec<Cow<'y, Value<'x, P, E>>>,
126 ) {
127 match pointer.next() {
128 Some(JsonPointerItem::Number(n)) => {
129 if let Some(v) = self.get(*n as usize) {
130 v.eval_jptr(pointer, results);
131 }
132 }
133 Some(JsonPointerItem::Wildcard) => {
134 for v in self {
135 v.eval_jptr(pointer.clone(), results);
136 }
137 }
138 Some(JsonPointerItem::Root) | None => {
139 results.push(self.to_value());
140 }
141 _ => {}
142 }
143 }
144
145 fn patch_jptr<'y: 'x>(
146 &mut self,
147 mut pointer: JsonPointerIter<'_, P>,
148 value: Value<'y, P, E>,
149 ) -> bool {
150 if let Some(JsonPointerItem::Number(n)) = pointer.next()
151 && let Some(item) = self.get_mut(*n as usize)
152 {
153 if pointer.peek().is_some() {
154 return item.patch_jptr(pointer, value);
155 } else if let Ok(value) = T::try_from(value) {
156 *item = value;
157 return true;
158 }
159 }
160 false
161 }
162
163 fn to_value<'y>(&'y self) -> Cow<'y, Value<'x, P, E>> {
164 Cow::Owned(Value::Array(
165 self.iter().map(|v| v.to_value().into_owned()).collect(),
166 ))
167 }
168}
169
170impl<'x, P: Property, E: Element, T> TryFrom<Value<'x, P, E>> for Vec<T>
171where
172 T: JsonPointerHandler<'x, P, E> + for<'y> TryFrom<Value<'y, P, E>> + 'static,
173{
174 type Error = ();
175
176 fn try_from(value: Value<'x, P, E>) -> Result<Self, Self::Error> {
177 if let Value::Array(arr) = value {
178 arr.into_iter()
179 .map(T::try_from)
180 .collect::<Result<Vec<_>, _>>()
181 .map_err(|_| ())
182 } else {
183 Err(())
184 }
185 }
186}
187
188impl<'x, P: Property, E: Element, T, S: BuildHasher + Default> JsonPointerHandler<'x, P, E>
189 for HashMap<String, T, S>
190where
191 T: JsonPointerHandler<'x, P, E> + for<'y> TryFrom<Value<'y, P, E>> + 'static,
192{
193 fn eval_jptr<'y>(
194 &'y self,
195 mut pointer: JsonPointerIter<'_, P>,
196 results: &mut Vec<Cow<'y, Value<'x, P, E>>>,
197 ) {
198 match pointer.next() {
199 Some(JsonPointerItem::Key(key)) => {
200 if let Some(v) = self.get(key.to_string().as_ref()) {
201 v.eval_jptr(pointer, results);
202 }
203 }
204 Some(JsonPointerItem::Number(n)) => {
205 let n = n.to_string();
206 if let Some(v) = self.get(&n) {
207 v.eval_jptr(pointer, results);
208 }
209 }
210 Some(JsonPointerItem::Wildcard) => {
211 for v in self.values() {
212 v.eval_jptr(pointer.clone(), results);
213 }
214 }
215 Some(JsonPointerItem::Root) | None => {
216 results.push(self.to_value());
217 }
218 }
219 }
220
221 fn patch_jptr<'y: 'x>(
222 &mut self,
223 mut pointer: JsonPointerIter<'_, P>,
224 value: Value<'y, P, E>,
225 ) -> bool {
226 match pointer.next() {
227 Some(JsonPointerItem::Key(key)) => {
228 let key = key.to_string();
229 if let Some(item) = self.get_mut(key.as_ref()) {
230 if pointer.peek().is_some() {
231 return item.patch_jptr(pointer, value);
232 } else if let Ok(value) = T::try_from(value) {
233 *item = value;
234 return true;
235 }
236 } else if pointer.next().is_none()
237 && let Ok(v) = T::try_from(value)
238 {
239 self.insert(key.into_owned(), v);
240 return true;
241 }
242 }
243 Some(JsonPointerItem::Number(n)) => {
244 if let Some(v) = self.get_mut(&n.to_string()) {
245 return v.patch_jptr(pointer, value);
246 }
247 }
248 Some(JsonPointerItem::Wildcard) | Some(JsonPointerItem::Root) | None => (),
249 }
250
251 false
252 }
253
254 fn to_value<'y>(&'y self) -> Cow<'y, Value<'x, P, E>> {
255 Cow::Owned(Value::Object(
256 self.iter()
257 .map(|(k, v)| (Key::Owned(k.to_string()), v.to_value().into_owned()))
258 .collect(),
259 ))
260 }
261}
262
263impl<'x, P: Property, E: Element, T> TryFrom<Value<'x, P, E>> for HashMap<String, T>
264where
265 T: JsonPointerHandler<'x, P, E> + for<'y> TryFrom<Value<'y, P, E>> + 'static,
266{
267 type Error = ();
268
269 fn try_from(value: Value<'x, P, E>) -> Result<Self, Self::Error> {
270 if let Value::Object(map) = value {
271 map.into_vec()
272 .into_iter()
273 .map(|(k, v)| T::try_from(v).map(|v| (k.to_string().into_owned(), v)))
274 .collect::<Result<HashMap<_, _>, _>>()
275 .map_err(|_| ())
276 } else {
277 Err(())
278 }
279 }
280}
281
282#[cfg(test)]
283mod tests {
284 use crate::{
285 Element, JsonPointer, JsonPointerHandler, JsonPointerItem, Key, Null, ObjectAsVec,
286 Property, Value, pointer::JsonPointerIter,
287 };
288 use serde::{Deserialize, Serialize, Serializer};
289 use std::{borrow::Cow, collections::HashMap};
290
291 #[derive(Debug, Clone, Serialize, Deserialize)]
292 struct SubObject {
293 text: String,
294 number: u64,
295 boolean: bool,
296 }
297
298 #[derive(Debug, Clone, Serialize, Deserialize)]
299 struct Object {
300 #[serde(serialize_with = "serialize_ordered_map")]
301 map: HashMap<String, SubObject>,
302 array: Vec<SubObject>,
303 value: SubObject,
304 }
305
306 #[test]
307 fn json_pointer() {
308 const TEST: &str = r#"
309 {
310 "map": {
311 "key1": {"text": "value1", "number": 1, "boolean": true},
312 "key2": {"text": "value2", "number": 2, "boolean": false}
313 },
314 "array": [
315 {"text": "item1", "number": 10, "boolean": true},
316 {"text": "item2", "number": 20, "boolean": false}
317 ],
318 "value": {"text": "single", "number": 100, "boolean": true}
319 }
320 "#;
321
322 let obj = serde_json::from_str::<Object>(TEST).unwrap();
323 let value = serde_json::from_str::<Value<'static, Null, Null>>(TEST).unwrap();
324
325 test_json_pointer(&obj, "object");
326 test_json_pointer(&value, "value");
327
328 test_json_patch(obj, "object");
329 test_json_patch(value, "value");
330 }
331
332 fn test_json_pointer<T, P, E>(obj: &T, test: &str)
333 where
334 T: JsonPointerHandler<'static, P, E>,
335 P: Property,
336 E: Element,
337 {
338 for (pointer, expected) in [
339 ("value/text", r#"["single"]"#),
340 ("value/number", r#"[100]"#),
341 ("value/boolean", r#"[true]"#),
342 (
343 "value",
344 r#"[{"text":"single","number":100,"boolean":true}]"#,
345 ),
346 ("map/key1/text", r#"["value1"]"#),
347 ("map/key1/number", r#"[1]"#),
348 ("map/key1/boolean", r#"[true]"#),
349 ("map/key2/text", r#"["value2"]"#),
350 ("map/key2/number", r#"[2]"#),
351 ("map/key2/boolean", r#"[false]"#),
352 ("array/0/text", r#"["item1"]"#),
353 ("array/0/number", r#"[10]"#),
354 ("array/0/boolean", r#"[true]"#),
355 ("array/1/text", r#"["item2"]"#),
356 ("array/1/number", r#"[20]"#),
357 ("array/1/boolean", r#"[false]"#),
358 ("map/*/text", r#"["value1","value2"]"#),
359 ("map/*/number", r#"[1,2]"#),
360 ("map/*/boolean", r#"[false,true]"#),
361 ("map/*/*", r#"["value1","value2",1,2,false,true]"#),
362 ("array/*/text", r#"["item1","item2"]"#),
363 ("array/*/number", r#"[10,20]"#),
364 ("array/*/boolean", r#"[false,true]"#),
365 ("array/*/*", r#"["item1","item2",10,20,false,true]"#),
366 ("/*/text", r#"["single"]"#),
367 ("/*/*/text", r#"["item1","item2","value1","value2"]"#),
368 ("/*/*/number", r#"[1,10,2,20]"#),
369 ("/*/*/boolean", r#"[false,false,true,true]"#),
370 ] {
371 let ptr = JsonPointer::parse(pointer);
372 let mut results = Vec::new();
373 obj.eval_jptr(ptr.iter(), &mut results);
374 results.sort_unstable_by_key(|a| a.to_string());
375 let results = serde_json::to_string(&results).unwrap();
376 if results != expected {
377 panic!(
378 "Pointer: {}\nTest: {}\nExpected: {}\nResults: {}",
379 pointer, test, expected, results
380 );
381 }
382 }
383 }
384
385 fn test_json_patch<T>(obj: T, test: &str)
386 where
387 T: JsonPointerHandler<'static, Null, Null> + Clone + Serialize,
388 {
389 for (pointer, patch, expected) in [
390 (
391 "value/text",
392 r#""hello""#,
393 r#""value":{"text":"hello","number":100,"boolean":true}"#,
394 ),
395 (
396 "value/number",
397 "123",
398 r#""value":{"text":"single","number":123,"boolean":true}"#,
399 ),
400 (
401 "value/boolean",
402 "false",
403 r#""value":{"text":"single","number":100,"boolean":false}"#,
404 ),
405 (
406 "value",
407 r#"{"text":"blah","number":999,"boolean":true}"#,
408 r#""value":{"text":"blah","number":999,"boolean":true}"#,
409 ),
410 (
411 "map/key1/text",
412 r#""hola""#,
413 r#"{"key1":{"text":"hola","number":1,"boolean":true},"key2":{"text":"value2","number":2,"boolean":false}}"#,
414 ),
415 (
416 "map/key1",
417 r#"{"text":"adios","number":123,"boolean":false}"#,
418 r#"{"key1":{"text":"adios","number":123,"boolean":false},"key2":{"text":"value2","number":2,"boolean":false}}"#,
419 ),
420 (
421 "array/1/text",
422 r#""nihao""#,
423 r#":[{"text":"item1","number":10,"boolean":true},{"text":"nihao","number":20,"boolean":false}]"#,
424 ),
425 (
426 "array/0",
427 r#"{"text":"bonjour","number":42,"boolean":true}"#,
428 r#"[{"text":"bonjour","number":42,"boolean":true},{"text":"item2","number":20,"boolean":false}]"#,
429 ),
430 ] {
431 let mut obj = obj.clone();
432 obj.patch_jptr(
433 JsonPointer::parse(pointer).iter(),
434 serde_json::from_str::<Value<'_, Null, Null>>(patch).unwrap(),
435 );
436
437 let results = serde_json::to_string(&obj).unwrap();
438 if !results.contains(expected) {
439 panic!(
440 "Pointer: {}\nTest: {}\nExpected: {}\nResults: {}",
441 pointer, test, expected, results
442 );
443 }
444 }
445 }
446
447 impl JsonPointerHandler<'static, Null, Null> for Object {
448 fn eval_jptr<'y>(
449 &'y self,
450 mut pointer: JsonPointerIter<'_, Null>,
451 results: &mut Vec<Cow<'y, Value<'static, Null, Null>>>,
452 ) {
453 match pointer.next() {
454 Some(JsonPointerItem::Key(key)) => {
455 let key = key.to_string();
456 if key == "map" {
457 self.map.eval_jptr(pointer, results);
458 } else if key == "array" {
459 self.array.eval_jptr(pointer, results);
460 } else if key == "value" {
461 if pointer.peek().is_none() {
462 results.push(self.value.to_value());
463 } else {
464 self.value.eval_jptr(pointer, results);
465 }
466 }
467 }
468 Some(JsonPointerItem::Wildcard) => {
469 self.map.eval_jptr(pointer.clone(), results);
470 self.array.eval_jptr(pointer.clone(), results);
471 self.value.eval_jptr(pointer.clone(), results);
472 }
473 Some(JsonPointerItem::Root) | None => {
474 results.push(self.to_value());
475 }
476 _ => {}
477 }
478 }
479
480 fn patch_jptr<'y: 'static>(
481 &mut self,
482 mut pointer: JsonPointerIter<'_, Null>,
483 value: Value<'y, Null, Null>,
484 ) -> bool {
485 if let Some(JsonPointerItem::Key(key)) = pointer.next() {
486 let key = key.to_string();
487 if pointer.peek().is_some() {
488 if key == "map" {
489 return self.map.patch_jptr(pointer, value);
490 } else if key == "array" {
491 return self.array.patch_jptr(pointer, value);
492 } else if key == "value" {
493 return self.value.patch_jptr(pointer, value);
494 }
495 } else if key == "map" {
496 if let Ok(v) = HashMap::<String, SubObject>::try_from(value) {
497 self.map = v;
498 return true;
499 }
500 } else if key == "array" {
501 if let Ok(v) = Vec::<SubObject>::try_from(value) {
502 self.array = v;
503 return true;
504 }
505 } else if key == "value"
506 && let Ok(v) = SubObject::try_from(value)
507 {
508 self.value = v;
509 return true;
510 }
511 }
512
513 false
514 }
515
516 fn to_value<'y>(&'y self) -> Cow<'y, Value<'static, Null, Null>> {
517 Cow::Owned(Value::Object(ObjectAsVec::from(vec![
518 (Key::Borrowed("map"), self.map.to_value().into_owned()),
519 (Key::Borrowed("array"), self.array.to_value().into_owned()),
520 (Key::Borrowed("value"), self.value.to_value().into_owned()),
521 ])))
522 }
523 }
524
525 impl JsonPointerHandler<'static, Null, Null> for SubObject {
526 fn eval_jptr<'y>(
527 &'y self,
528 mut pointer: JsonPointerIter<'_, Null>,
529 results: &mut Vec<Cow<'y, Value<'_, Null, Null>>>,
530 ) {
531 match pointer.next() {
532 Some(JsonPointerItem::Key(s)) => match s.to_string().as_ref() {
533 "text" => results.push(Cow::Owned(Value::Str(self.text.clone().into()))),
534 "number" => results.push(Cow::Owned(Value::Number(self.number.into()))),
535 "boolean" => results.push(Cow::Owned(Value::Bool(self.boolean))),
536 _ => {}
537 },
538 Some(JsonPointerItem::Wildcard) if pointer.peek().is_none() => {
539 results.push(Cow::Owned(Value::Str(self.text.clone().into())));
540 results.push(Cow::Owned(Value::Number(self.number.into())));
541 results.push(Cow::Owned(Value::Bool(self.boolean)));
542 }
543 _ => {}
544 }
545 }
546
547 fn patch_jptr<'y: 'static>(
548 &mut self,
549 mut pointer: JsonPointerIter<'_, Null>,
550 value: Value<'y, Null, Null>,
551 ) -> bool {
552 if let Some(JsonPointerItem::Key(s)) = pointer.next() {
553 let has_next = pointer.next().is_some();
554 match s.to_string().as_ref() {
555 "text" if !has_next => {
556 if let Some(text) = value.into_string() {
557 self.text = text.into_owned();
558 return true;
559 }
560 }
561 "number" if !has_next => {
562 if let Some(number) = value.as_u64() {
563 self.number = number;
564 return true;
565 }
566 }
567 "boolean" if !has_next => {
568 if let Some(boolean) = value.as_bool() {
569 self.boolean = boolean;
570 return true;
571 }
572 }
573 _ => {}
574 }
575 }
576
577 false
578 }
579
580 fn to_value<'y>(&'y self) -> Cow<'y, Value<'static, Null, Null>> {
581 Cow::Owned(Value::Object(ObjectAsVec::from(vec![
582 (Key::Borrowed("text"), Value::Str(self.text.clone().into())),
583 (Key::Borrowed("number"), Value::Number(self.number.into())),
584 (Key::Borrowed("boolean"), Value::Bool(self.boolean)),
585 ])))
586 }
587 }
588
589 impl TryFrom<Value<'_, Null, Null>> for SubObject {
590 type Error = ();
591
592 fn try_from(value: Value<'_, Null, Null>) -> Result<Self, Self::Error> {
593 if let Value::Object(map) = value {
594 let text = map
595 .get(&Key::Borrowed("text"))
596 .and_then(|v| v.as_str())
597 .unwrap_or_default()
598 .into_owned();
599 let number = map
600 .get(&Key::Borrowed("number"))
601 .and_then(Value::as_u64)
602 .unwrap_or(0);
603 let boolean = map
604 .get(&Key::Borrowed("boolean"))
605 .and_then(Value::as_bool)
606 .unwrap_or(false);
607 Ok(SubObject {
608 text,
609 number,
610 boolean,
611 })
612 } else {
613 Err(())
614 }
615 }
616 }
617
618 fn serialize_ordered_map<S>(
619 map: &HashMap<String, SubObject>,
620 serializer: S,
621 ) -> Result<S::Ok, S::Error>
622 where
623 S: Serializer,
624 {
625 let mut sorted_pairs: Vec<_> = map.iter().collect();
626 sorted_pairs.sort_by_key(|(k, _)| *k);
627
628 use serde::ser::SerializeMap;
629 let mut map_serializer = serializer.serialize_map(Some(sorted_pairs.len()))?;
630 for (k, v) in sorted_pairs {
631 map_serializer.serialize_entry(k, v)?;
632 }
633 map_serializer.end()
634 }
635}