jsonpath_rust/path/
top.rs

1use crate::jsp_obj;
2use crate::parser::model::*;
3use crate::path::{json_path_instance, JsonPathValue, Path};
4use crate::JsonPathValue::{NewValue, NoValue, Slice};
5
6use super::{JsonLike, TopPaths};
7
8/// to process the element [*]
9pub struct Wildcard<T> {
10    _t: std::marker::PhantomData<T>,
11}
12
13impl<T> Wildcard<T> {
14    pub fn new() -> Self {
15        Self {
16            _t: std::marker::PhantomData,
17        }
18    }
19}
20
21impl<T> Default for Wildcard<T> {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl<'a, T> Path<'a> for Wildcard<T>
28where
29    T: JsonLike,
30{
31    type Data = T;
32
33    fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
34        data.flat_map_slice(|data, pref| data.itre(pref))
35    }
36}
37
38/// empty path. Returns incoming data.
39pub struct IdentityPath<T> {
40    _t: std::marker::PhantomData<T>,
41}
42
43impl<T> Default for IdentityPath<T> {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49impl<T> IdentityPath<T> {
50    pub fn new() -> Self {
51        Self {
52            _t: std::marker::PhantomData,
53        }
54    }
55}
56
57impl<'a, T> Path<'a> for IdentityPath<T> {
58    type Data = T;
59
60    fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
61        vec![data]
62    }
63}
64
65pub(crate) struct EmptyPath<T> {
66    _t: std::marker::PhantomData<T>,
67}
68
69impl<'a, T> Path<'a> for EmptyPath<T> {
70    type Data = T;
71
72    fn find(&self, _data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
73        vec![]
74    }
75}
76
77/// process $ element
78pub struct RootPointer<'a, T> {
79    root: &'a T,
80}
81
82impl<'a, T> RootPointer<'a, T> {
83    pub(crate) fn new(root: &'a T) -> RootPointer<'a, T> {
84        RootPointer { root }
85    }
86}
87
88impl<'a, T> Path<'a> for RootPointer<'a, T>
89where
90    T: JsonLike,
91{
92    type Data = T;
93
94    fn find(&self, _data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
95        vec![JsonPathValue::from_root(self.root)]
96    }
97}
98
99/// process object fields like ['key'] or .key
100pub struct ObjectField<'a, T> {
101    key: &'a str,
102    _t: std::marker::PhantomData<T>,
103}
104
105impl<'a, T> ObjectField<'a, T> {
106    pub(crate) fn new(key: &'a str) -> ObjectField<'a, T> {
107        ObjectField {
108            key,
109            _t: std::marker::PhantomData,
110        }
111    }
112}
113
114impl<T> Clone for ObjectField<'_, T> {
115    fn clone(&self) -> Self {
116        ObjectField::new(self.key)
117    }
118}
119
120impl<'a, T> Path<'a> for ObjectField<'a, T>
121where
122    T: JsonLike,
123{
124    type Data = T;
125
126    fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
127        let take_field = |v: &'a T| v.get(self.key);
128
129        let res = match data {
130            Slice(js, p) => take_field(js)
131                .map(|v| JsonPathValue::new_slice(v, jsp_obj(&p, self.key)))
132                .unwrap_or_else(|| NoValue),
133            _ => NoValue,
134        };
135        vec![res]
136    }
137}
138
139pub enum FnPath<T> {
140    Size { _t: std::marker::PhantomData<T> },
141}
142
143impl<T> FnPath<T> {
144    pub fn new_size() -> Self {
145        FnPath::Size {
146            _t: std::marker::PhantomData,
147        }
148    }
149}
150
151impl<'a, T> Path<'a> for FnPath<T>
152where
153    T: JsonLike,
154{
155    type Data = T;
156
157    fn flat_find(
158        &self,
159        input: Vec<JsonPathValue<'a, Self::Data>>,
160        is_search_length: bool,
161    ) -> Vec<JsonPathValue<'a, Self::Data>> {
162        // todo rewrite
163        if JsonPathValue::only_no_value(&input) {
164            return vec![NoValue];
165        }
166        let res = if is_search_length {
167            NewValue(T::init_with_usize(
168                input.iter().filter(|v| v.has_value()).count(),
169            ))
170        } else {
171            match input.first() {
172                Some(v) => match v {
173                    NewValue(d) => d.array_len(),
174                    Slice(s, _) => s.array_len(),
175                    NoValue => NoValue,
176                },
177                None => NoValue,
178            }
179        };
180        vec![res]
181    }
182
183    fn needs_all(&self) -> bool {
184        true
185    }
186}
187
188/// the top method of the processing ..*
189pub struct DescentWildcard<T> {
190    _t: std::marker::PhantomData<T>,
191}
192
193impl<T> Default for DescentWildcard<T> {
194    fn default() -> Self {
195        Self::new()
196    }
197}
198
199impl<T> DescentWildcard<T> {
200    pub fn new() -> Self {
201        DescentWildcard {
202            _t: std::marker::PhantomData,
203        }
204    }
205}
206
207impl<'a, T> Path<'a> for DescentWildcard<T>
208where
209    T: JsonLike,
210{
211    type Data = T;
212
213    fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
214        data.map_slice(|data, pref| data.deep_flatten(pref))
215    }
216}
217
218/// processes decent object like ..
219pub struct DescentObject<'a, T> {
220    key: &'a str,
221    _t: std::marker::PhantomData<T>,
222}
223
224impl<'a, T> Path<'a> for DescentObject<'a, T>
225where
226    T: JsonLike,
227{
228    type Data = T;
229
230    fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
231        data.flat_map_slice(|data, pref| {
232            let res_col = data.deep_path_by_key(ObjectField::new(self.key), pref.clone());
233            if res_col.is_empty() {
234                vec![NoValue]
235            } else {
236                JsonPathValue::map_vec(res_col)
237            }
238        })
239    }
240}
241
242impl<'a, T> DescentObject<'a, T> {
243    pub fn new(key: &'a str) -> Self {
244        DescentObject {
245            key,
246            _t: std::marker::PhantomData,
247        }
248    }
249}
250
251/// the top method of the processing representing the chain of other operators
252pub struct Chain<'a, T> {
253    chain: Vec<TopPaths<'a, T>>,
254    is_search_length: bool,
255}
256
257impl<'a, T> Chain<'a, T>
258where
259    T: JsonLike,
260{
261    pub fn new(chain: Vec<TopPaths<'a, T>>, is_search_length: bool) -> Self {
262        Chain {
263            chain,
264            is_search_length,
265        }
266    }
267    pub fn from(chain: &'a [JsonPath<T>], root: &'a T) -> Self {
268        let chain_len = chain.len();
269        let is_search_length = if chain_len > 2 {
270            let mut res = false;
271            // if the result of the slice expected to be a slice, union or filter -
272            // length should return length of resulted array
273            // In all other cases, including single index, we should fetch item from resulting array
274            // and return length of that item
275            res = match chain.get(chain_len - 1).expect("chain element disappeared") {
276                JsonPath::Fn(Function::Length) => {
277                    for item in chain.iter() {
278                        match (item, res) {
279                            // if we found union, slice, filter or wildcard - set search to true
280                            (
281                                JsonPath::Index(JsonPathIndex::UnionIndex(_))
282                                | JsonPath::Index(JsonPathIndex::UnionKeys(_))
283                                | JsonPath::Index(JsonPathIndex::Slice(_, _, _))
284                                | JsonPath::Index(JsonPathIndex::Filter(_))
285                                | JsonPath::Wildcard,
286                                false,
287                            ) => {
288                                res = true;
289                            }
290                            // if we found a fetching of single index - reset search to false
291                            (JsonPath::Index(JsonPathIndex::Single(_)), true) => {
292                                res = false;
293                            }
294                            (_, _) => {}
295                        }
296                    }
297                    res
298                }
299                _ => false,
300            };
301            res
302        } else {
303            false
304        };
305
306        Chain::new(
307            chain.iter().map(|p| json_path_instance(p, root)).collect(),
308            is_search_length,
309        )
310    }
311}
312
313impl<'a, T> Path<'a> for Chain<'a, T>
314where
315    T: JsonLike,
316{
317    type Data = T;
318
319    fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
320        let mut res = vec![data];
321
322        for inst in self.chain.iter() {
323            if inst.needs_all() {
324                res = inst.flat_find(res, self.is_search_length)
325            } else {
326                res = res.into_iter().flat_map(|d| inst.find(d)).collect()
327            }
328        }
329        res
330    }
331}
332
333#[cfg(test)]
334mod tests {
335    use crate::jp_v;
336    use crate::parser::macros::{chain, idx};
337    use crate::parser::model::{JsonPath, JsonPathIndex};
338    use crate::path;
339    use crate::path::top::{json_path_instance, Function, ObjectField, RootPointer};
340    use crate::path::{JsonPathValue, Path};
341    use crate::JsonPathValue::NoValue;
342    use serde_json::json;
343    use serde_json::Value;
344
345    #[test]
346    fn object_test() {
347        let js = json!({"product": {"key":42}});
348        let res_income = jp_v!(&js);
349
350        let key = String::from("product");
351        let mut field = ObjectField::new(&key);
352        let js = json!({"key":42});
353        assert_eq!(
354            field.find(res_income.clone()),
355            vec![jp_v!(&js;".['product']")]
356        );
357
358        let key = String::from("fake");
359        field.key = &key;
360        assert_eq!(field.find(res_income), vec![NoValue]);
361    }
362
363    #[test]
364    fn root_test() {
365        let res_income = json!({"product": {"key":42}});
366
367        let root = RootPointer::<Value>::new(&res_income);
368
369        assert_eq!(root.find(jp_v!(&res_income)), jp_v!(&res_income;"$",))
370    }
371
372    #[test]
373    fn path_instance_test() {
374        let json = json!({"v": {"k":{"f":42,"array":[0,1,2,3,4,5],"object":{"field1":"val1","field2":"val2"}}}});
375        let field1 = path!("v");
376        let field2 = path!("k");
377        let field3 = path!("f");
378        let field4 = path!("array");
379        let field5 = path!("object");
380
381        let path_inst = json_path_instance(&path!($), &json);
382        assert_eq!(path_inst.find(jp_v!(&json)), jp_v!(&json;"$",));
383
384        let path_inst = json_path_instance(&field1, &json);
385        let exp_json =
386            json!({"k":{"f":42,"array":[0,1,2,3,4,5],"object":{"field1":"val1","field2":"val2"}}});
387        assert_eq!(path_inst.find(jp_v!(&json)), jp_v!(&exp_json;".['v']",));
388
389        let chain = chain!(path!($), field1.clone(), field2.clone(), field3);
390
391        let path_inst = json_path_instance(&chain, &json);
392        let exp_json = json!(42);
393        assert_eq!(
394            path_inst.find(jp_v!(&json)),
395            jp_v!(&exp_json;"$.['v'].['k'].['f']",)
396        );
397
398        let chain = chain!(
399            path!($),
400            field1.clone(),
401            field2.clone(),
402            field4.clone(),
403            path!(idx!(3))
404        );
405        let path_inst = json_path_instance(&chain, &json);
406        let exp_json = json!(3);
407        assert_eq!(
408            path_inst.find(jp_v!(&json)),
409            jp_v!(&exp_json;"$.['v'].['k'].['array'][3]",)
410        );
411
412        let index = idx!([1;-1;2]);
413        let chain = chain!(
414            path!($),
415            field1.clone(),
416            field2.clone(),
417            field4.clone(),
418            path!(index)
419        );
420        let path_inst = json_path_instance(&chain, &json);
421        let one = json!(1);
422        let tree = json!(3);
423        assert_eq!(
424            path_inst.find(jp_v!(&json)),
425            jp_v!(&one;"$.['v'].['k'].['array'][1]", &tree;"$.['v'].['k'].['array'][3]")
426        );
427
428        let union = idx!(idx 1,2 );
429        let chain = chain!(
430            path!($),
431            field1.clone(),
432            field2.clone(),
433            field4,
434            path!(union)
435        );
436        let path_inst = json_path_instance(&chain, &json);
437        let tree = json!(1);
438        let two = json!(2);
439        assert_eq!(
440            path_inst.find(jp_v!(&json)),
441            jp_v!(&tree;"$.['v'].['k'].['array'][1]",&two;"$.['v'].['k'].['array'][2]")
442        );
443
444        let union = idx!("field1", "field2");
445        let chain = chain!(path!($), field1.clone(), field2, field5, path!(union));
446        let path_inst = json_path_instance(&chain, &json);
447        let one = json!("val1");
448        let two = json!("val2");
449        assert_eq!(
450            path_inst.find(jp_v!(&json)),
451            jp_v!(
452            &one;"$.['v'].['k'].['object'].['field1']",
453            &two;"$.['v'].['k'].['object'].['field2']")
454        );
455    }
456    #[test]
457    fn path_descent_arr_test() {
458        let json = json!([{"a":1}]);
459        let chain = chain!(path!($), path!(.."a"));
460        let path_inst = json_path_instance(&chain, &json);
461
462        let one = json!(1);
463        let expected_res = jp_v!(&one;"$[0].['a']",);
464        assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
465    }
466    #[test]
467    fn deep_path_test() {
468        use crate::path::JsonLike;
469        let value = json!([1]);
470        let r = value.deep_flatten("".to_string());
471        assert_eq!(r, vec![(&json!(1), "[0]".to_string())])
472    }
473
474    #[test]
475    fn path_descent_w_array_test() {
476        let json = json!(
477        {
478            "key1": [1]
479        });
480        let chain = chain!(path!($), path!(..*));
481        let path_inst = json_path_instance(&chain, &json);
482
483        let arr = json!([1]);
484        let one = json!(1);
485
486        let expected_res = jp_v!(&arr;"$.['key1']",&one;"$.['key1'][0]");
487        assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
488    }
489    #[test]
490    fn path_descent_w_nested_array_test() {
491        let json = json!(
492        {
493            "key2" : [{"a":1},{}]
494        });
495        let chain = chain!(path!($), path!(..*));
496        let path_inst = json_path_instance(&chain, &json);
497
498        let arr2 = json!([{"a": 1},{}]);
499        let obj = json!({"a": 1});
500        let empty = json!({});
501
502        let one = json!(1);
503
504        let expected_res = jp_v!(
505            &arr2;"$.['key2']",
506            &obj;"$.['key2'][0]",
507            &one;"$.['key2'][0].['a']",
508            &empty;"$.['key2'][1]"
509        );
510        assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
511    }
512
513    #[test]
514    fn path_descent_w_test() {
515        let json = json!(
516        {
517            "key1": [1],
518            "key2": "key",
519            "key3": {
520                "key1": "key1",
521                "key2": {
522                    "key1": {
523                        "key1": 0
524                         }
525                     }
526            }
527        });
528        let chain = chain!(path!($), path!(..*));
529        let path_inst = json_path_instance(&chain, &json);
530
531        let key1 = json!([1]);
532        let one = json!(1);
533        let zero = json!(0);
534        let key = json!("key");
535        let key1_s = json!("key1");
536
537        let key_3 = json!(  {
538          "key1": "key1",
539          "key2": {
540            "key1": {
541              "key1": 0
542            }
543          }
544        });
545        let key_sec = json!(    {
546          "key1": {
547            "key1": 0
548          }
549        });
550        let key_th = json!(  {
551          "key1": 0
552        });
553
554        let expected_res = vec![
555            jp_v!(&key1;"$.['key1']"),
556            jp_v!(&one;"$.['key1'][0]"),
557            jp_v!(&key;"$.['key2']"),
558            jp_v!(&key_3;"$.['key3']"),
559            jp_v!(&key1_s;"$.['key3'].['key1']"),
560            jp_v!(&key_sec;"$.['key3'].['key2']"),
561            jp_v!(&key_th;"$.['key3'].['key2'].['key1']"),
562            jp_v!(&zero;"$.['key3'].['key2'].['key1'].['key1']"),
563        ];
564        assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
565    }
566    #[test]
567    fn path_descent_test() {
568        let json = json!(
569        {
570            "key1": [1,2,3],
571            "key2": "key",
572            "key3": {
573                "key1": "key1",
574                "key2": {
575                    "key1": {
576                        "key1": 0
577                         }
578                     }
579            }
580        });
581        let chain = chain!(path!($), path!(.."key1"));
582        let path_inst = json_path_instance(&chain, &json);
583
584        let res1 = json!([1, 2, 3]);
585        let res2 = json!("key1");
586        let res3 = json!({"key1":0});
587        let res4 = json!(0);
588
589        let expected_res = jp_v!(
590            &res1;"$.['key1']",
591            &res2;"$.['key3'].['key1']",
592            &res3;"$.['key3'].['key2'].['key1']",
593            &res4;"$.['key3'].['key2'].['key1'].['key1']",
594        );
595        assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
596    }
597
598    #[test]
599    fn wildcard_test() {
600        let json = json!({
601            "key1": [1,2,3],
602            "key2": "key",
603            "key3": {}
604        });
605
606        let chain = chain!(path!($), path!(*));
607        let path_inst = json_path_instance(&chain, &json);
608
609        let res1 = json!([1, 2, 3]);
610        let res2 = json!("key");
611        let res3 = json!({});
612
613        let expected_res = jp_v!(&res1;"$.['key1']", &res2;"$.['key2']", &res3;"$.['key3']");
614        assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
615    }
616
617    #[test]
618    fn length_test() {
619        let json = json!({
620            "key1": [1,2,3],
621            "key2": "key",
622            "key3": {}
623        });
624
625        let chain = chain!(path!($), path!(*), JsonPath::Fn(Function::Length));
626        let path_inst = json_path_instance(&chain, &json);
627
628        assert_eq!(
629            path_inst.flat_find(vec![jp_v!(&json)], true),
630            vec![jp_v!(json!(3))]
631        );
632
633        let chain = chain!(path!($), path!("key1"), JsonPath::Fn(Function::Length));
634        let path_inst = json_path_instance(&chain, &json);
635        assert_eq!(
636            path_inst.flat_find(vec![jp_v!(&json)], false),
637            vec![jp_v!(json!(3))]
638        );
639    }
640}