1use std::fmt::{Display, Formatter};
2use std::hash::Hash;
3
4use data_encoding::BASE32_DNSSEC;
5use itertools::Itertools as _;
6use schemars::JsonSchema;
7use schemars::r#gen::SchemaGenerator;
8use schemars::schema::Schema;
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10use serde_json::Value;
11use sha2::{Digest as _, Sha256};
12
13use crate::segment::common::anonymize::Anonymize;
14use crate::segment::common::utils::{MultiValue, merge_map};
15
16mod parse;
17
18#[derive(Debug, Clone, PartialEq, Eq, Ord, Hash, PartialOrd)]
19pub struct JsonPath {
20 pub first_key: String,
21 pub rest: Vec<JsonPathItem>,
22}
23
24#[derive(Debug, PartialEq, Clone, Eq, Ord, Hash, PartialOrd)]
25pub enum JsonPathItem {
26 Key(String),
28 Index(usize),
31 WildcardIndex,
33}
34
35impl JsonPath {
36 #[cfg(feature = "testing")]
42 pub fn new(p: &str) -> Self {
43 p.parse().unwrap()
44 }
45
46 pub fn value_get<'a>(
48 &self,
49 json_map: &'a serde_json::Map<String, Value>,
50 ) -> MultiValue<&'a Value> {
51 let mut result = MultiValue::new();
52 if let Some(value) = json_map.get(&self.first_key) {
53 value_get(&self.rest, Some(value), &mut result);
54 }
55 result
56 }
57
58 pub fn value_set<'a>(
60 path: Option<&Self>,
61 dest: &'a mut serde_json::Map<String, Value>,
62 src: &'a serde_json::Map<String, Value>,
63 ) {
64 if let Some(path) = path {
65 value_set_map(&path.first_key, &path.rest, dest, src);
66 } else {
67 merge_map(dest, src);
68 }
69 }
70
71 pub fn value_remove(&self, json_map: &mut serde_json::Map<String, Value>) -> MultiValue<Value> {
73 let mut result = MultiValue::new();
74 if let Some((rest1, restn)) = self.rest.split_first() {
75 if let Some(value) = json_map.get_mut(&self.first_key) {
76 value_remove(rest1, restn, value, &mut result);
77 }
78 } else if let Some(value) = json_map.remove(&self.first_key) {
79 result.push(value);
80 }
81 result
82 }
83
84 pub fn value_filter(
86 json_map: &serde_json::Map<String, Value>,
87 filter: impl Fn(&Self, &Value) -> bool,
88 ) -> serde_json::Map<String, Value> {
89 let mut new_map = serde_json::Map::new();
90 let mut path = JsonPath {
91 first_key: "".to_string(),
92 rest: Vec::new(),
93 };
94 for (key, value) in json_map.iter() {
95 path.first_key.clone_from(key);
96 if filter(&path, value) {
97 let value = run_filter(&mut path, value, &filter);
98 new_map.insert(key.clone(), value);
99 }
100 }
101 new_map
102 }
103
104 pub fn strip_wildcard_suffix(&self) -> Self {
107 match self.rest.split_last() {
108 Some((JsonPathItem::WildcardIndex, rest)) => JsonPath {
109 first_key: self.first_key.clone(),
110 rest: rest.to_vec(),
111 },
112 _ => self.clone(),
113 }
114 }
115
116 pub fn strip_prefix(&self, prefix: &Self) -> Option<Self> {
118 if self.first_key != prefix.first_key {
119 return None;
120 }
121 let mut self_it = self.rest.iter().peekable();
122 let mut prefix_it = prefix.rest.iter().peekable();
123 loop {
124 match (self_it.peek(), prefix_it.peek()) {
125 (Some(self_item), Some(prefix_item)) if self_item == prefix_item => {
126 self_it.next();
127 prefix_it.next();
128 }
129 (Some(_), Some(_)) => return None,
130 (Some(JsonPathItem::Key(k)), None) => {
131 return Some(JsonPath {
132 first_key: k.clone(),
133 rest: self_it.skip(1).cloned().collect(),
134 });
135 }
136 (Some(_), None) => {
137 return None;
140 }
141 (None, Some(_)) => return None,
142 (None, None) => {
143 return None;
145 }
146 }
147 }
148 }
149
150 pub fn extend(&self, other: &Self) -> Self {
152 let mut rest = Vec::with_capacity(self.rest.len() + 1 + other.rest.len());
153 rest.extend_from_slice(&self.rest);
154 rest.push(JsonPathItem::Key(other.first_key.clone()));
155 rest.extend_from_slice(&other.rest);
156 JsonPath {
157 first_key: self.first_key.clone(),
158 rest,
159 }
160 }
161
162 pub fn array_key(&self) -> Self {
165 let mut result = JsonPath {
166 first_key: self.first_key.clone(),
167 rest: Vec::with_capacity(self.rest.len() + 1),
168 };
169 result.rest.extend_from_slice(&self.rest);
170 if result.rest.last() != Some(&JsonPathItem::WildcardIndex) {
171 result.rest.push(JsonPathItem::WildcardIndex);
172 }
173 result
174 }
175
176 pub fn has_wildcard_suffix(&self) -> bool {
177 self.rest.last() == Some(&JsonPathItem::WildcardIndex)
178 }
179
180 pub fn check_include_pattern(&self, pattern: &Self) -> bool {
184 self.first_key == pattern.first_key
185 && self.rest.iter().zip(&pattern.rest).all(|(a, b)| a == b)
186 }
187
188 pub fn check_exclude_pattern(&self, pattern: &Self) -> bool {
192 self.first_key == pattern.first_key && pattern.rest.starts_with(&self.rest)
193 }
194
195 pub fn extend_or_new(base: Option<&Self>, other: &Self) -> Self {
196 base.map_or_else(|| other.clone(), |base| base.extend(other))
197 }
198
199 pub fn compatible(&self, other: &Self) -> bool {
201 if self.first_key != other.first_key {
202 return false;
203 }
204 self.rest
205 .iter()
206 .zip(&other.rest)
207 .all(|(a, b)| match (a, b) {
208 (JsonPathItem::Key(a), JsonPathItem::Key(b)) => a == b,
209 (JsonPathItem::Index(a), JsonPathItem::Index(b)) => a == b,
210 (JsonPathItem::WildcardIndex, JsonPathItem::WildcardIndex) => true,
211 (JsonPathItem::Index(_), JsonPathItem::WildcardIndex) => true,
212 (JsonPathItem::WildcardIndex, JsonPathItem::Index(_)) => true,
213 _ => false,
214 })
215 }
216
217 pub fn is_affected_by_value_remove(&self, path_to_remove: &JsonPath) -> bool {
219 path_to_remove.compatible(self)
222 }
223
224 pub fn is_affected_by_value_set(
226 &self,
227 payload: &serde_json::Map<String, Value>,
228 path_to_set: Option<&JsonPath>,
229 ) -> bool {
230 let Some(path_to_set) = path_to_set else {
245 return payload.contains_key(&self.first_key);
246 };
247 if self.first_key != path_to_set.first_key {
248 return false;
249 }
250 let mut it_a = self.rest.iter();
251 let mut it_b = path_to_set.rest.iter();
252 loop {
253 let (a, b) = match (it_a.next(), it_b.next()) {
254 (Some(a), Some(b)) => (a, b),
255 (None, _) => return true, (Some(JsonPathItem::Key(a)), None) => return payload.contains_key(a),
258 (Some(JsonPathItem::Index(_)), None) => return true,
259 (Some(JsonPathItem::WildcardIndex), None) => return true,
260 };
261
262 match (a, b) {
263 (JsonPathItem::Key(a), JsonPathItem::Key(b)) if a == b => (),
265 (JsonPathItem::Index(a), JsonPathItem::Index(b)) if a == b => (),
266 (JsonPathItem::WildcardIndex, JsonPathItem::WildcardIndex) => (),
267 (JsonPathItem::Index(_), JsonPathItem::WildcardIndex) => (),
268 (JsonPathItem::WildcardIndex, JsonPathItem::Index(_)) => (),
269
270 (JsonPathItem::Key(_), JsonPathItem::Key(_)) => return false,
274 (JsonPathItem::Index(_), JsonPathItem::Index(_)) => return false,
275
276 (JsonPathItem::Key(_), JsonPathItem::Index(_) | JsonPathItem::WildcardIndex) => {
279 return true;
280 }
281 (JsonPathItem::Index(_) | JsonPathItem::WildcardIndex, JsonPathItem::Key(_)) => {
282 return true;
283 }
284 }
285 }
286 }
287
288 pub fn filename(&self) -> String {
291 const MAX_LENGTH: usize = 33;
292 const HASH_LENGTH: usize = 24; let text = self.to_string();
295 let mut result = String::with_capacity(MAX_LENGTH);
296
297 BASE32_DNSSEC.encode_append(
298 &Sha256::digest(text.as_bytes())[0..(HASH_LENGTH * 5).div_ceil(8)],
299 &mut result,
300 );
301 debug_assert_eq!(result.len(), HASH_LENGTH);
302
303 result.push('-');
304
305 text.chars()
306 .map(|c| match c {
307 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' => c.to_ascii_lowercase(),
308 _ => '_',
309 })
310 .dedup_by(|&a, &b| a == '_' && b == '_')
311 .take(MAX_LENGTH - result.len())
312 .for_each(|c| result.push(c));
313
314 debug_assert!(result.len() <= MAX_LENGTH);
315 result
316 }
317}
318
319fn value_get<'a>(
320 path: &[JsonPathItem],
321 value: Option<&'a Value>,
322 result: &mut MultiValue<&'a Value>,
323) {
324 if let Some((head, tail)) = path.split_first() {
325 match (head, value) {
326 (JsonPathItem::Key(key), Some(Value::Object(map))) => {
327 value_get(tail, map.get(key), result)
328 }
329 (JsonPathItem::Index(index), Some(Value::Array(array))) => {
330 if let Some(value) = array.get(*index) {
331 value_get(tail, Some(value), result);
332 }
333 }
334 (JsonPathItem::WildcardIndex, Some(Value::Array(array))) => array
335 .iter()
336 .for_each(|value| value_get(tail, Some(value), result)),
337 _ => (),
338 }
339 } else if let Some(value) = value {
340 result.push(value);
341 }
342}
343
344fn value_set(path: &[JsonPathItem], dest: &mut Value, src: &serde_json::Map<String, Value>) {
345 if let Some((head, rest)) = path.split_first() {
346 match head {
347 JsonPathItem::Key(key) => {
348 if !dest.is_object() {
349 *dest = Value::Object(serde_json::Map::new());
350 }
351 let map = dest.as_object_mut().unwrap();
352 value_set_map(key, rest, map, src);
353 }
354 &JsonPathItem::Index(i) => {
355 if !dest.is_array() {
356 *dest = Value::Array(Vec::new());
357 }
358 let array = dest.as_array_mut().unwrap();
359 if let Some(v) = array.get_mut(i) {
360 value_set(rest, v, src);
361 }
362 }
363 JsonPathItem::WildcardIndex => {
364 if dest.is_array() {
365 for value in dest.as_array_mut().unwrap() {
366 value_set(rest, value, src);
367 }
368 } else {
369 *dest = Value::Array(Vec::new());
370 }
371 }
372 }
373 } else {
374 if !dest.is_object() {
375 *dest = Value::Object(serde_json::Map::new());
376 }
377 let map = dest.as_object_mut().unwrap();
378 merge_map(map, src);
379 }
380}
381
382fn value_set_map(
383 key: &str,
384 path: &[JsonPathItem],
385 dest_map: &mut serde_json::Map<String, Value>,
386 src: &serde_json::Map<String, Value>,
387) {
388 if let Some(value) = dest_map.get_mut(key) {
389 value_set(path, value, src);
390 } else {
391 let mut value = Value::Null;
392 value_set(path, &mut value, src);
393 dest_map.insert(key.to_string(), value);
394 }
395}
396
397fn value_remove(
398 head: &JsonPathItem,
399 rest: &[JsonPathItem],
400 value: &mut Value,
401 result: &mut MultiValue<Value>,
402) {
403 if let Some((rest1, restn)) = rest.split_first() {
404 match (head, value) {
405 (JsonPathItem::Key(k), Value::Object(map)) => {
406 if let Some(value) = map.get_mut(k) {
407 value_remove(rest1, restn, value, result);
408 }
409 }
410 (JsonPathItem::Index(i), Value::Array(array)) => {
411 if let Some(value) = array.get_mut(*i) {
412 value_remove(rest1, restn, value, result);
413 }
414 }
415 (JsonPathItem::WildcardIndex, Value::Array(array)) => {
416 for value in array {
417 value_remove(rest1, restn, value, result);
418 }
419 }
420 _ => (),
421 }
422 } else {
423 match (head, value) {
424 (JsonPathItem::Key(k), Value::Object(map)) => {
425 if let Some(v) = map.remove(k) {
426 result.push(v);
427 }
428 }
429 (JsonPathItem::Index(_), Value::Array(_)) => {
430 }
432 (JsonPathItem::WildcardIndex, Value::Array(array)) => {
433 result.push(Value::Array(std::mem::take(array)));
434 }
435 _ => (),
436 }
437 }
438}
439
440fn run_filter<'a>(
441 path: &mut JsonPath,
442 value: &'a Value,
443 filter: &dyn Fn(&JsonPath, &Value) -> bool,
444) -> Value {
445 match &value {
446 Value::Null => value.clone(),
447 Value::Bool(_) => value.clone(),
448 Value::Number(_) => value.clone(),
449 Value::String(_) => value.clone(),
450 Value::Array(array) => {
451 let mut new_array = Vec::new();
452 path.rest.push(JsonPathItem::WildcardIndex);
453 for value in array.iter() {
454 if filter(path, value) {
455 let value = run_filter(path, value, filter);
456 new_array.push(value);
457 }
458 }
459 path.rest.pop();
460 Value::Array(new_array)
461 }
462 Value::Object(object) => {
463 let mut new_object = serde_json::Map::new();
464 for (key, value) in object.iter() {
465 path.rest.push(JsonPathItem::Key(key.clone()));
466 if filter(path, value) {
467 let value = run_filter(path, value, filter);
468 new_object.insert(key.clone(), value);
469 }
470 path.rest.pop();
471 }
472 Value::Object(new_object)
473 }
474 }
475}
476
477impl Display for JsonPath {
478 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
479 let write_key = |f: &mut Formatter<'_>, key: &str| {
480 if parse::key_needs_quoting(key) {
481 write!(f, "\"{key}\"")
482 } else {
483 f.write_str(key)
484 }
485 };
486
487 write_key(f, &self.first_key)?;
488 for item in &self.rest {
489 match item {
490 JsonPathItem::Key(key) => {
491 f.write_str(".")?;
492 write_key(f, key)?;
493 }
494 JsonPathItem::Index(index) => write!(f, "[{index}]")?,
495 JsonPathItem::WildcardIndex => f.write_str("[]")?,
496 }
497 }
498 Ok(())
499 }
500}
501
502impl TryFrom<&str> for JsonPath {
503 type Error = ();
504
505 fn try_from(value: &str) -> Result<Self, Self::Error> {
506 value.parse()
507 }
508}
509
510impl Serialize for JsonPath {
511 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
512 serializer.serialize_str(&self.to_string())
513 }
514}
515
516impl<'de> Deserialize<'de> for JsonPath {
517 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
518 let string = String::deserialize(deserializer)?;
519 string
520 .parse()
521 .map_err(|_| serde::de::Error::custom(format!("Invalid json path: \'{string}\'")))
522 }
523}
524
525impl JsonSchema for JsonPath {
526 fn is_referenceable() -> bool {
527 false
528 }
529
530 fn schema_name() -> String {
531 "JsonPath".to_string()
532 }
533
534 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
535 String::json_schema(generator)
536 }
537}
538
539#[cfg(test)]
540mod tests {
541 use super::*;
542 use crate::segment::common::utils::check_is_empty;
543
544 fn json(str: &str) -> serde_json::Map<String, Value> {
545 serde_json::from_str(str).unwrap()
546 }
547
548 #[test]
549 fn test_is_affected_by_value_set() {
550 assert!(!JsonPath::new("a").is_affected_by_value_set(&json(r#"{"b": 1, "c": 1}"#), None));
551 assert!(JsonPath::new("a").is_affected_by_value_set(&json(r#"{"a": 1, "b": 1}"#), None));
552 assert!(JsonPath::new("a.x").is_affected_by_value_set(&json(r#"{"a": {"y": 1}}"#), None));
553 assert!(!JsonPath::new("a.x").is_affected_by_value_set(&json(r#"{"b": {"x": 1}}"#), None));
554 }
555
556 #[test]
557 fn test_is_affected_by_value_remove() {
558 assert!(JsonPath::new("a").is_affected_by_value_remove(&JsonPath::new("a")));
559 assert!(!JsonPath::new("a").is_affected_by_value_remove(&JsonPath::new("b")));
560 assert!(JsonPath::new("a.b").is_affected_by_value_remove(&JsonPath::new("a")));
561 assert!(JsonPath::new("a.b").is_affected_by_value_remove(&JsonPath::new("a.b")));
562 assert!(JsonPath::new("a.b").is_affected_by_value_remove(&JsonPath::new("a.b.c")));
563 }
564
565 #[test]
570 fn test_no_false_negatives() {
571 let paths: Vec<JsonPath> = ["a", "a.a", "a[]", "a[0]", "a[0].a", "a[0].a[]"]
572 .iter()
573 .map(|s| s.parse().unwrap())
574 .collect();
575 let payloads = vec![
576 json(r#"{"b": 1}"#),
577 json(r#"{"a": 1, "b": 2}"#),
578 json(r#"{"a": [], "b": 1}"#),
579 json(r#"{"a": [1], "b": 2}"#),
580 json(r#"{"a": {}, "b": 1}"#),
581 json(r#"{"a": {"a": 1, "b": 2}, "b": 3}"#),
582 json(r#"{"a": [{"a": 1, "b": 2}, {"a": 3, "b": 4}], "b": 5}"#),
583 json(r#"{"a": [{"a": [1], "b": 2}, {"a": [3], "b": 4}], "b": 5}"#),
584 ];
585
586 for init_payload in &payloads {
587 for indexed_path in &paths {
588 for value_key in &["a", "b"] {
589 check_set(init_payload, indexed_path, None, value_key);
590 for path_to_set in &paths {
591 check_set(init_payload, indexed_path, Some(path_to_set), value_key);
592 }
593 }
594 for path_to_remove in &paths {
595 check_remove(init_payload, indexed_path, path_to_remove);
596 }
597 }
598 }
599 }
600
601 fn check_set(
602 init_payload: &serde_json::Map<String, serde_json::Value>,
603 indexed_path: &JsonPath,
604 path_to_set: Option<&JsonPath>,
605 value_key: &str,
606 ) {
607 let mut new_payload = init_payload.clone();
608 let init_values = indexed_path.value_get(init_payload);
609
610 JsonPath::value_set(
611 path_to_set,
612 &mut new_payload,
613 &json(r#"{"value_key": 100}"#),
614 );
615 let new_values = indexed_path.value_get(&new_payload);
616
617 let indexed_value_changed = init_values != new_values;
619
620 let is_affected =
622 indexed_path.is_affected_by_value_set(&json(r#"{"value_key": 100}"#), path_to_set);
623
624 assert!(
625 is_affected || !indexed_value_changed,
626 "init_payload: {:?}\nnew_payload: {:?}\nindex_path: {:?}\npath_to_set: {:?}\nvalue_key: {:?}",
627 init_payload,
628 new_payload,
629 indexed_path.to_string(),
630 path_to_set.map(|p| p.to_string()),
631 value_key,
632 );
633 }
634
635 fn check_remove(
636 init_payload: &serde_json::Map<String, serde_json::Value>,
637 indexed_path: &JsonPath,
638 path_to_remove: &JsonPath,
639 ) {
640 let mut new_payload = init_payload.clone();
641 let init_values = indexed_path.value_get(init_payload);
642 path_to_remove.value_remove(&mut new_payload);
643 let new_values = indexed_path.value_get(&new_payload);
644
645 let indexed_value_changed = init_values != new_values;
647
648 let is_affected = indexed_path.is_affected_by_value_remove(path_to_remove);
650
651 assert!(
652 is_affected || !indexed_value_changed,
653 "init_payload: {:?}\nnew_payload: {:?}\nindex_path: {:?}\npath_to_remove: {:?}",
654 init_payload,
655 new_payload,
656 indexed_path.to_string(),
657 path_to_remove.to_string(),
658 );
659 }
660
661 #[test]
662 fn test_get_nested_value_from_json_map() {
663 let map = json(
664 r#"
665 {
666 "a": {"b": {"c": 1}},
667 "d": 2
668 }
669 "#,
670 );
671
672 assert_eq!(
673 JsonPath::new("a.b").value_get(&map).into_vec(),
674 vec![&Value::Object(serde_json::Map::from_iter(vec![(
675 "c".to_string(),
676 Value::Number(1.into())
677 )]))]
678 );
679
680 assert_eq!(
682 JsonPath::new("a.b.c").value_get(&map).into_vec(),
683 vec![&Value::Number(1.into())]
684 );
685
686 assert!(check_is_empty(
688 JsonPath::new("a.b.c.d").value_get(&map).iter().copied()
689 ));
690 }
691
692 #[test]
693 fn test_is_empty() {
694 let map = json(
695 r#"
696 {
697 "a": [
698 { "b": 1 },
699 { "b": 2 },
700 { "b": null },
701 { "d": [] },
702 { "d": [] },
703 { "f": null }
704 ]
705 }
706 "#,
707 );
708 let multivalue = JsonPath::new("a[].b").value_get(&map);
709 let is_empty = check_is_empty(multivalue.iter().copied());
710
711 assert!(!is_empty, "a[].b is not empty");
712
713 let multivalue = JsonPath::new("a[].c").value_get(&map);
714 let is_empty = check_is_empty(multivalue.iter().copied());
715
716 assert!(is_empty, "a[].c is empty");
717
718 let multivalue = JsonPath::new("a[].d").value_get(&map);
719 let is_empty = check_is_empty(multivalue.iter().copied());
720 assert!(is_empty, "a[].d is empty");
721
722 let multivalue = JsonPath::new("a[].f").value_get(&map);
723 let is_empty = check_is_empty(multivalue.iter().copied());
724 assert!(is_empty, "a[].f is empty");
725 }
726
727 #[test]
728 fn test_get_nested_array_value_from_json_map() {
729 let map = json(
730 r#"
731 {
732 "a": {
733 "b": [
734 { "c": 1 },
735 { "c": 2 },
736 { "d": { "e": 3 } }
737 ]
738 },
739 "f": 3,
740 "g": ["g0", "g1", "g2"]
741 }
742 "#,
743 );
744
745 assert_eq!(
747 JsonPath::new("a.b").value_get(&map).into_vec(),
748 vec![&Value::Array(vec![
749 Value::Object(serde_json::Map::from_iter(vec![(
750 "c".to_string(),
751 Value::Number(1.into())
752 )])),
753 Value::Object(serde_json::Map::from_iter(vec![(
754 "c".to_string(),
755 Value::Number(2.into())
756 )])),
757 Value::Object(serde_json::Map::from_iter(vec![(
758 "d".to_string(),
759 Value::Object(serde_json::Map::from_iter(vec![(
760 "e".to_string(),
761 Value::Number(3.into())
762 )]))
763 )]))
764 ])]
765 );
766
767 assert_eq!(
769 JsonPath::new("a.b[]").value_get(&map).into_vec(),
770 vec![
771 &Value::Object(serde_json::Map::from_iter(vec![(
772 "c".to_string(),
773 Value::Number(1.into())
774 )])),
775 &Value::Object(serde_json::Map::from_iter(vec![(
776 "c".to_string(),
777 Value::Number(2.into())
778 )])),
779 &Value::Object(serde_json::Map::from_iter(vec![(
780 "d".to_string(),
781 Value::Object(serde_json::Map::from_iter(vec![(
782 "e".to_string(),
783 Value::Number(3.into())
784 )]))
785 )]))
786 ]
787 );
788
789 assert_eq!(
791 JsonPath::new("a.b[].c").value_get(&map).into_vec(),
792 vec![&Value::Number(1.into()), &Value::Number(2.into())]
793 );
794
795 assert_eq!(
797 JsonPath::new("a.b[].d").value_get(&map).into_vec(),
798 vec![&Value::Object(serde_json::Map::from_iter(vec![(
799 "e".to_string(),
800 Value::Number(3.into())
801 )]))]
802 );
803
804 assert_eq!(
806 JsonPath::new("a.b[0]").value_get(&map).into_vec(),
807 vec![&Value::Object(serde_json::Map::from_iter(vec![(
808 "c".to_string(),
809 Value::Number(1.into())
810 )]))]
811 );
812
813 assert_eq!(
815 JsonPath::new("a.b[1]").value_get(&map).into_vec(),
816 vec![&Value::Object(serde_json::Map::from_iter(vec![(
817 "c".to_string(),
818 Value::Number(2.into())
819 )]))]
820 );
821
822 assert_eq!(
824 JsonPath::new("a.b[1].c").value_get(&map).into_vec(),
825 vec![&Value::Number(2.into())]
826 );
827
828 assert_eq!(
830 JsonPath::new("g[2]").value_get(&map).into_vec(),
831 vec![&Value::String("g2".to_string())]
832 );
833
834 assert_eq!(
836 JsonPath::new("a.b[2]").value_get(&map).into_vec(),
837 vec![&Value::Object(serde_json::Map::from_iter(vec![(
838 "d".to_string(),
839 Value::Object(serde_json::Map::from_iter(vec![(
840 "e".to_string(),
841 Value::Number(3.into())
842 )]))
843 )]))]
844 );
845
846 assert!(check_is_empty(
848 JsonPath::new("a.b[3]").value_get(&map).iter().copied()
849 ));
850 }
851
852 #[test]
853 fn test_get_deeply_nested_array_value_from_json_map() {
854 let map = json(
855 r#"
856 {
857 "arr1": [
858 {
859 "arr2": [
860 {"a": 1, "b": 2}
861 ]
862 },
863 {
864 "arr2": [
865 {"a": 3, "b": 4},
866 {"a": 5, "b": 6}
867 ]
868 }
869 ]
870 }
871 "#,
872 );
873
874 assert_eq!(
876 JsonPath::new("arr1[].arr2[].a").value_get(&map).into_vec(),
877 vec![
878 &Value::Number(1.into()),
879 &Value::Number(3.into()),
880 &Value::Number(5.into()),
881 ]
882 );
883 }
884
885 #[test]
886 fn test_no_flatten_array_value_from_json_map() {
887 let map = json(
888 r#"
889 {
890 "arr": [
891 { "a": [1, 2, 3] },
892 { "a": 4 },
893 { "b": 5 }
894 ]
895 }
896 "#,
897 );
898
899 assert_eq!(
901 JsonPath::new("arr[].a").value_get(&map).into_vec(),
902 vec![
903 &Value::Array(vec![
904 Value::Number(1.into()),
905 Value::Number(2.into()),
906 Value::Number(3.into()),
907 ]),
908 &Value::Number(4.into()),
909 ]
910 );
911
912 assert_eq!(
914 JsonPath::new("arr[].a[]").value_get(&map).into_vec(),
915 vec![
916 &Value::Number(1.into()),
917 &Value::Number(2.into()),
918 &Value::Number(3.into()),
919 ]
920 );
921 }
922
923 #[test]
924 fn test_get_null_and_absent_values() {
925 let map = json(
926 r#"
927 {
928 "a": null,
929 "b": [null, null],
930 "c": []
931 }
932 "#,
933 );
934
935 assert_eq!(
936 JsonPath::new("a").value_get(&map).as_slice(),
937 &[&Value::Null],
938 );
939
940 assert!(JsonPath::new("a[]").value_get(&map).is_empty());
941
942 assert_eq!(
943 JsonPath::new("b").value_get(&map).as_slice(),
944 &[&Value::Array(vec![Value::Null, Value::Null])],
945 );
946
947 assert_eq!(
948 JsonPath::new("b[]").value_get(&map).as_slice(),
949 &[&Value::Null, &Value::Null],
950 );
951
952 assert_eq!(
953 JsonPath::new("c").value_get(&map).as_slice(),
954 &[&Value::Array(vec![])],
955 );
956
957 assert!(JsonPath::new("c[]").value_get(&map).is_empty());
958
959 assert!(JsonPath::new("d").value_get(&map).is_empty());
960
961 assert!(JsonPath::new("d[]").value_get(&map).is_empty());
962 }
963
964 #[test]
965 fn test_filter_json() {
966 let map = json(
967 r#"
968 {
969 "a": {
970 "b": [
971 { "c": 1 },
972 { "c": 2 },
973 { "d": { "e": 3 } }
974 ]
975 },
976 "f": 3,
977 "g": ["g0", "g1", "g2"]
978 }
979 "#,
980 );
981
982 let res = JsonPath::value_filter(&map, |path, _value| {
983 let path = path.to_string();
984 path.starts_with("a.b[].c") || "a.b[].c".starts_with(&path)
985 });
986
987 assert_eq!(
988 res,
989 json(
990 r#"
991 {
992 "a": {
993 "b": [
994 { "c": 1 },
995 { "c": 2 },
996 {}
997 ]
998 }
999 }
1000 "#,
1001 ),
1002 );
1003 }
1004
1005 #[test]
1006 fn test_check_include_pattern() {
1007 assert!(JsonPath::new("a.b.c").check_include_pattern(&JsonPath::new("a.b.c")));
1008 assert!(JsonPath::new("a.b.c").check_include_pattern(&JsonPath::new("a.b")));
1009 assert!(!JsonPath::new("a.b.c").check_include_pattern(&JsonPath::new("a.b.d")));
1010 assert!(JsonPath::new("a.b.c").check_include_pattern(&JsonPath::new("a")));
1011 assert!(JsonPath::new("a").check_include_pattern(&JsonPath::new("a.d")));
1012 }
1013
1014 #[test]
1015 fn test_check_exclude_pattern() {
1016 assert!(JsonPath::new("a.b.c").check_exclude_pattern(&JsonPath::new("a.b.c")));
1017 assert!(!JsonPath::new("a.b.c").check_exclude_pattern(&JsonPath::new("a.b")));
1018 assert!(!JsonPath::new("a.b.c").check_exclude_pattern(&JsonPath::new("a.b.d")));
1019 assert!(!JsonPath::new("a.b.c").check_exclude_pattern(&JsonPath::new("a")));
1020 assert!(JsonPath::new("a").check_exclude_pattern(&JsonPath::new("a.d")));
1021 }
1022
1023 #[test]
1024 fn test_set_value_to_json_with_empty_key() {
1025 let mut map = json(
1026 r#"
1027 {
1028 "a": {
1029 "b": [
1030 { "c": 1 },
1031 { "c": 2 },
1032 { "d": { "e": 3 } }
1033 ]
1034 },
1035 "f": 3,
1036 "g": ["g0", "g1", "g2"]
1037 }
1038 "#,
1039 );
1040
1041 JsonPath::value_set(None, &mut map, &json(r#"{"c": 5}"#));
1042
1043 assert_eq!(
1044 map,
1045 json(
1046 r#"
1047 {
1048 "a": {
1049 "b": [
1050 { "c": 1 },
1051 { "c": 2 },
1052 { "d": { "e": 3 } }
1053 ]
1054 },
1055 "f": 3,
1056 "g": ["g0", "g1", "g2"],
1057 "c": 5
1058 }
1059 "#,
1060 ),
1061 );
1062 }
1063
1064 #[test]
1065 fn test_set_value_to_json_with_one_level_key() {
1066 let mut map = json(
1067 r#"
1068 {
1069 "a": {
1070 "b": [
1071 { "c": 1 },
1072 { "c": 2 },
1073 { "d": { "e": 3 } }
1074 ]
1075 },
1076 "f": 3,
1077 "g": ["g0", "g1", "g2"]
1078 }
1079 "#,
1080 );
1081
1082 JsonPath::value_set(Some(&JsonPath::new("a")), &mut map, &json(r#"{"b": 5}"#));
1083
1084 assert_eq!(
1085 map,
1086 json(
1087 r#"
1088 {
1089 "a": {
1090 "b": 5
1091 },
1092 "f": 3,
1093 "g": ["g0", "g1", "g2"]
1094 }
1095 "#,
1096 ),
1097 );
1098 }
1099
1100 #[test]
1101 fn test_set_value_to_json_with_array_index() {
1102 let mut map = json(
1103 r#"
1104 {
1105 "a": {
1106 "b": [
1107 { "c": 1 },
1108 { "c": 2 },
1109 { "d": { "e": 3 } }
1110 ]
1111 },
1112 "f": 3,
1113 "g": ["g0", "g1", "g2"]
1114 }
1115 "#,
1116 );
1117
1118 JsonPath::value_set(
1119 Some(&JsonPath::new("a.b[1]")),
1120 &mut map,
1121 &json(r#"{"c": 5}"#),
1122 );
1123
1124 assert_eq!(
1125 map,
1126 json(
1127 r#"
1128 {
1129 "a": {
1130 "b": [
1131 { "c": 1 },
1132 { "c": 5 },
1133 { "d": { "e": 3 } }
1134 ]
1135 },
1136 "f": 3,
1137 "g": ["g0", "g1", "g2"]
1138 }
1139 "#,
1140 ),
1141 );
1142 }
1143
1144 #[test]
1145 fn test_set_value_to_json_with_empty_src() {
1146 let mut map = json(
1147 r#"
1148 {
1149 "a": {
1150 "b": [
1151 { "c": 1 },
1152 { "c": 2 },
1153 { "d": { "e": 3 } }
1154 ]
1155 },
1156 "f": 3,
1157 "g": ["g0", "g1", "g2"]
1158 }
1159 "#,
1160 );
1161
1162 JsonPath::value_set(Some(&JsonPath::new("a.b[1]")), &mut map, &json("{}"));
1163
1164 assert_eq!(
1165 map,
1166 json(
1167 r#"
1168 {
1169 "a": {
1170 "b": [
1171 { "c": 1 },
1172 { "c": 2 },
1173 { "d": { "e": 3 } }
1174 ]
1175 },
1176 "f": 3,
1177 "g": ["g0", "g1", "g2"]
1178 }
1179 "#,
1180 ),
1181 );
1182 }
1183
1184 #[test]
1185 fn test_set_value_to_json_with_empty_dest() {
1186 let mut map = json("{}");
1187
1188 JsonPath::value_set(None, &mut map, &json(r#"{"c": 1}"#));
1189
1190 assert_eq!(map, json(r#"{"c": 1}"#));
1191 }
1192
1193 #[test]
1194 fn test_set_value_to_json_with_empty_dest_nested_key() {
1195 let mut map = json("{}");
1196
1197 JsonPath::value_set(
1198 Some(&JsonPath::new("key1.key2")),
1199 &mut map,
1200 &json(r#"{"c": 1}"#),
1201 );
1202
1203 assert_eq!(map, json(r#"{"key1": {"key2": {"c": 1}}}"#));
1204 }
1205
1206 #[test]
1207 fn test_set_value_to_json_with_empty_dest_nested_array_index_key() {
1208 let mut map = json("{}");
1209 let src = json(r#"{"c": 1}"#);
1210 JsonPath::value_set(Some(&JsonPath::new("key1.key2[3]")), &mut map, &src);
1211 assert_eq!(map, json(r#" {"key1": {"key2": []}} "#));
1212
1213 let mut map = json("{}");
1214 let src = json(r#"{"c": 1}"#);
1215 JsonPath::value_set(Some(&JsonPath::new("key1.key2[0]")), &mut map, &src);
1216 assert_eq!(map, json(r#" {"key1": {"key2": []}} "#));
1217 }
1218
1219 #[test]
1220 fn test_expand_payload_with_non_existing_array() {
1221 let mut map = json("{}");
1222
1223 JsonPath::value_set(
1224 Some(&JsonPath::new("key1.key2[].key3")),
1225 &mut map,
1226 &json(r#"{"c": 1}"#),
1227 );
1228
1229 assert_eq!(map, json(r#"{"key1": {"key2": [] }}"#));
1230 }
1231
1232 #[test]
1233 fn test_replace_scalar_key_with_object() {
1234 let mut map = json(r#"{"a": 10}"#);
1235
1236 JsonPath::value_set(
1237 Some(&JsonPath::new("a.b.c")),
1238 &mut map,
1239 &json(r#"{"x": 1}"#),
1240 );
1241
1242 assert_eq!(map, json(r#"{"a": {"b": {"c": {"x": 1}}}}"#));
1243 }
1244
1245 #[test]
1246 fn test_remove_key() {
1247 let mut payload = json(
1248 r#"
1249 {
1250 "a": 1,
1251 "b": {
1252 "c": 123,
1253 "e": {
1254 "f": [1,2,3],
1255 "g": 7,
1256 "h": "text",
1257 "i": [
1258 {
1259 "j": 1,
1260 "k": 2
1261 },
1262 {
1263 "j": 3,
1264 "k": 4
1265 }
1266 ]
1267 }
1268 }
1269 }
1270 "#,
1271 );
1272 let removed = JsonPath::new("b.c").value_remove(&mut payload).into_vec();
1273 assert_eq!(removed, vec![Value::Number(123.into())]);
1274 assert_ne!(payload, Default::default());
1275
1276 let removed = JsonPath::new("b.e.i[0].j")
1277 .value_remove(&mut payload)
1278 .into_vec();
1279 assert_eq!(removed, vec![Value::Number(1.into())]);
1280 assert_ne!(payload, Default::default());
1281
1282 let removed = JsonPath::new("b.e.i[].k")
1283 .value_remove(&mut payload)
1284 .into_vec();
1285 assert_eq!(
1286 removed,
1287 vec![Value::Number(2.into()), Value::Number(4.into())]
1288 );
1289 assert_ne!(payload, Default::default());
1290
1291 let removed = JsonPath::new("b.e.i[]")
1292 .value_remove(&mut payload)
1293 .into_vec();
1294 assert_eq!(
1295 removed,
1296 vec![Value::Array(vec![
1297 Value::Object(serde_json::Map::from_iter(vec![])),
1298 Value::Object(serde_json::Map::from_iter(vec![(
1299 "j".to_string(),
1300 Value::Number(3.into())
1301 ),])),
1302 ])]
1303 );
1304 assert_ne!(payload, Default::default());
1305
1306 let removed = JsonPath::new("b.e.i").value_remove(&mut payload).into_vec();
1307 assert_eq!(removed, vec![Value::Array(vec![])]);
1308 assert_ne!(payload, Default::default());
1309
1310 let removed = JsonPath::new("b.e.f").value_remove(&mut payload).into_vec();
1311 assert_eq!(
1312 removed,
1313 vec![Value::Array(vec![1.into(), 2.into(), 3.into()])]
1314 );
1315 assert_ne!(payload, Default::default());
1316
1317 let removed = JsonPath::new("k").value_remove(&mut payload);
1318 assert!(check_is_empty(&removed));
1319 assert_ne!(payload, Default::default());
1320
1321 let removed = JsonPath::new("b.e.l").value_remove(&mut payload);
1322 assert!(check_is_empty(&removed));
1323 assert_ne!(payload, Default::default());
1324
1325 let removed = JsonPath::new("a").value_remove(&mut payload).into_vec();
1326 assert_eq!(removed, vec![Value::Number(1.into())]);
1327 assert_ne!(payload, Default::default());
1328
1329 let removed = JsonPath::new("b.e").value_remove(&mut payload).into_vec();
1330 assert_eq!(
1331 removed,
1332 vec![Value::Object(serde_json::Map::from_iter(vec![
1333 ("g".to_string(), Value::Number(7.into())),
1335 ("h".to_string(), Value::String("text".to_owned())),
1336 ]))]
1337 );
1338 assert_ne!(payload, Default::default());
1339
1340 let removed = JsonPath::new("b").value_remove(&mut payload).into_vec();
1341 assert_eq!(
1342 removed,
1343 vec![Value::Object(serde_json::Map::from_iter(vec![]))]
1344 ); assert_eq!(payload, Default::default());
1346 }
1347
1348 #[test]
1349 fn test_filename() {
1350 assert_eq!(
1351 JsonPath::new("foo").filename(),
1352 "5gjb8qr8vv38vucr8ku1qc21-foo",
1353 );
1354 assert_eq!(
1355 JsonPath::new("a.\"b c\".d").filename(),
1356 "59if87e118rvurkl7j0q10mc-a_b_c_d",
1357 );
1358 assert_eq!(
1359 JsonPath::new("a.b[0][]").filename(),
1360 "vk82udqfa8drecufa7j5mo6v-a_b_0_",
1361 );
1362 assert_eq!(
1363 JsonPath::new("really.loooooooooooooooooooooooooooooooooooooooooooong.path").filename(),
1364 "sh47i3hjfgn44gch5jvm3bum-really_l",
1365 );
1366 assert_eq!(
1367 JsonPath::new("Müesli").filename(),
1368 "4huj4rn1fflrtriqo0tieqhh-m_esli",
1369 );
1370 }
1371}