jsonpath_rust/
jsonpath.rs

1use crate::path::json_path_instance;
2use crate::path::JsonLike;
3use crate::JsonPathValue;
4use crate::JsonPtr;
5use crate::{JsonPath, JsonPathStr};
6
7impl<T> JsonPath<T>
8where
9    T: JsonLike,
10{
11    /// finds a slice of data in the set json.
12    /// The result is a vector of references to the incoming structure.
13    ///
14    /// In case, if there is no match [`Self::find_slice`] will return vec!<[`JsonPathValue::NoValue`]>.
15    ///
16    /// ## Example
17    /// ```rust
18    /// use jsonpath_rust::{JsonPath, JsonPathValue};
19    /// use serde_json::json;
20    /// # use std::str::FromStr;
21    ///
22    /// let data = json!({"first":{"second":[{"active":1},{"passive":1}]}});
23    /// let path = JsonPath::try_from("$.first.second[?(@.active)]").unwrap();
24    /// let slice_of_data = path.find_slice(&data);
25    ///
26    /// let expected_value = json!({"active":1});
27    /// let expected_path = "$.['first'].['second'][0]".to_string();
28    ///
29    /// assert_eq!(
30    ///     slice_of_data,
31    ///     vec![JsonPathValue::Slice(&expected_value, expected_path)]
32    /// );
33    /// ```
34    pub fn find_slice<'a>(&'a self, json: &'a T) -> Vec<JsonPathValue<'a, T>> {
35        use crate::path::Path;
36        let instance = json_path_instance(self, json);
37        let res = instance.find(JsonPathValue::from_root(json));
38        let has_v: Vec<JsonPathValue<'_, T>> = res.into_iter().filter(|v| v.has_value()).collect();
39
40        if has_v.is_empty() {
41            vec![JsonPathValue::NoValue]
42        } else {
43            has_v
44        }
45    }
46
47    /// like [`Self::find_slice`] but returns a vector of [`JsonPtr`], which has no [`JsonPathValue::NoValue`].
48    /// if there is no match, it will return an empty vector
49    pub fn find_slice_ptr<'a>(&'a self, json: &'a T) -> Vec<JsonPtr<'a, T>> {
50        use crate::path::Path;
51        json_path_instance(self, json)
52            .find(JsonPathValue::from_root(json))
53            .into_iter()
54            .filter(|v| v.has_value())
55            .map(|v| match v {
56                JsonPathValue::Slice(v, _) => JsonPtr::Slice(v),
57                JsonPathValue::NewValue(v) => JsonPtr::NewValue(v),
58                JsonPathValue::NoValue => unreachable!("has_value was already checked"),
59            })
60            .collect()
61    }
62
63    /// finds a slice of data and wrap it with Value::Array by cloning the data.
64    /// Returns either an array of elements or Json::Null if the match is incorrect.
65    ///
66    /// In case, if there is no match `find` will return `json!(null)`.
67    ///
68    /// ## Example
69    /// ```rust
70    /// use jsonpath_rust::{JsonPath, JsonPathValue};
71    /// use serde_json::{Value, json};
72    /// # use std::str::FromStr;
73    ///
74    /// let data = json!({"first":{"second":[{"active":1},{"passive":1}]}});
75    /// let path = JsonPath::try_from("$.first.second[?(@.active)]").unwrap();
76    /// let cloned_data = path.find(&data);
77    ///
78    /// assert_eq!(cloned_data, Value::Array(vec![json!({"active":1})]));
79    /// ```
80    pub fn find(&self, json: &T) -> T {
81        let slice = self.find_slice(json);
82        if !slice.is_empty() {
83            if JsonPathValue::only_no_value(&slice) {
84                T::null()
85            } else {
86                T::array(
87                    slice
88                        .into_iter()
89                        .filter(|v| v.has_value())
90                        .map(|v| v.to_data())
91                        .collect(),
92                )
93            }
94        } else {
95            T::array(vec![])
96        }
97    }
98
99    /// finds a path describing the value, instead of the value itself.
100    /// If the values has been obtained by moving the data out of the initial json the path is absent.
101    ///
102    /// ** If the value has been modified during the search, there is no way to find a path of a new value.
103    /// It can happen if we try to find a length() of array, for in stance.**
104    ///
105    /// ## Example
106    /// ```rust
107    /// use jsonpath_rust::{JsonPathStr, JsonPath, JsonPathValue};
108    /// use serde_json::{Value, json};
109    /// # use std::str::FromStr;
110    ///
111    /// let data = json!({"first":{"second":[{"active":1},{"passive":1}]}});
112    /// let path = JsonPath::try_from("$.first.second[?(@.active)]").unwrap();
113    /// let slice_of_data: Vec<JsonPathStr> = path.find_as_path(&data);
114    ///
115    /// let expected_path = "$.['first'].['second'][0]".to_string();
116    /// assert_eq!(slice_of_data, vec![expected_path]);
117    /// ```
118    pub fn find_as_path(&self, json: &T) -> Vec<JsonPathStr> {
119        self.find_slice(json)
120            .into_iter()
121            .flat_map(|v| v.to_path())
122            .collect()
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use crate::path::JsonLike;
129    use crate::JsonPathQuery;
130    use crate::JsonPathValue::{NoValue, Slice};
131    use crate::{jp_v, JsonPath, JsonPathParserError, JsonPathValue};
132    use serde_json::{json, Value};
133    use std::ops::Deref;
134
135    fn test(json: &str, path: &str, expected: Vec<JsonPathValue<Value>>) {
136        let json: Value = match serde_json::from_str(json) {
137            Ok(json) => json,
138            Err(e) => panic!("error while parsing json: {}", e),
139        };
140        let path = match JsonPath::try_from(path) {
141            Ok(path) => path,
142            Err(e) => panic!("error while parsing jsonpath: {}", e),
143        };
144
145        assert_eq!(path.find_slice(&json), expected)
146    }
147
148    fn template_json<'a>() -> &'a str {
149        r#" {"store": { "book": [
150             {
151                 "category": "reference",
152                 "author": "Nigel Rees",
153                 "title": "Sayings of the Century",
154                 "price": 8.95
155             },
156             {
157                 "category": "fiction",
158                 "author": "Evelyn Waugh",
159                 "title": "Sword of Honour",
160                 "price": 12.99
161             },
162             {
163                 "category": "fiction",
164                 "author": "Herman Melville",
165                 "title": "Moby Dick",
166                 "isbn": "0-553-21311-3",
167                 "price": 8.99
168             },
169             {
170                 "category": "fiction",
171                 "author": "J. R. R. Tolkien",
172                 "title": "The Lord of the Rings",
173                 "isbn": "0-395-19395-8",
174                 "price": 22.99
175             }
176         ],
177         "bicycle": {
178             "color": "red",
179             "price": 19.95
180         }
181     },
182     "array":[0,1,2,3,4,5,6,7,8,9],
183     "orders":[
184         {
185             "ref":[1,2,3],
186             "id":1,
187             "filled": true
188         },
189         {
190             "ref":[4,5,6],
191             "id":2,
192             "filled": false
193         },
194         {
195             "ref":[7,8,9],
196             "id":3,
197             "filled": null
198         }
199      ],
200     "expensive": 10 }"#
201    }
202
203    #[test]
204    fn simple_test() {
205        let j1 = json!(2);
206        test("[1,2,3]", "$[1]", jp_v![&j1;"$[1]",]);
207    }
208
209    #[test]
210    fn root_test() {
211        let js = serde_json::from_str(template_json()).unwrap();
212        test(template_json(), "$", jp_v![&js;"$",]);
213    }
214
215    #[test]
216    fn descent_test() {
217        let v1 = json!("reference");
218        let v2 = json!("fiction");
219        test(
220            template_json(),
221            "$..category",
222            jp_v![
223                 &v1;"$.['store'].['book'][0].['category']",
224                 &v2;"$.['store'].['book'][1].['category']",
225                 &v2;"$.['store'].['book'][2].['category']",
226                 &v2;"$.['store'].['book'][3].['category']",],
227        );
228        let js1 = json!(19.95);
229        let js2 = json!(8.95);
230        let js3 = json!(12.99);
231        let js4 = json!(8.99);
232        let js5 = json!(22.99);
233        test(
234            template_json(),
235            "$.store..price",
236            jp_v![
237                &js1;"$.['store'].['bicycle'].['price']",
238                &js2;"$.['store'].['book'][0].['price']",
239                &js3;"$.['store'].['book'][1].['price']",
240                &js4;"$.['store'].['book'][2].['price']",
241                &js5;"$.['store'].['book'][3].['price']",
242            ],
243        );
244        let js1 = json!("Nigel Rees");
245        let js2 = json!("Evelyn Waugh");
246        let js3 = json!("Herman Melville");
247        let js4 = json!("J. R. R. Tolkien");
248        test(
249            template_json(),
250            "$..author",
251            jp_v![
252            &js1;"$.['store'].['book'][0].['author']",
253            &js2;"$.['store'].['book'][1].['author']",
254            &js3;"$.['store'].['book'][2].['author']",
255            &js4;"$.['store'].['book'][3].['author']",],
256        );
257    }
258
259    #[test]
260    fn wildcard_test() {
261        let js1 = json!("reference");
262        let js2 = json!("fiction");
263        test(
264            template_json(),
265            "$..book.[*].category",
266            jp_v![
267                &js1;"$.['store'].['book'][0].['category']",
268                &js2;"$.['store'].['book'][1].['category']",
269                &js2;"$.['store'].['book'][2].['category']",
270                &js2;"$.['store'].['book'][3].['category']",],
271        );
272        let js1 = json!("Nigel Rees");
273        let js2 = json!("Evelyn Waugh");
274        let js3 = json!("Herman Melville");
275        let js4 = json!("J. R. R. Tolkien");
276        test(
277            template_json(),
278            "$.store.book[*].author",
279            jp_v![
280                &js1;"$.['store'].['book'][0].['author']",
281                &js2;"$.['store'].['book'][1].['author']",
282                &js3;"$.['store'].['book'][2].['author']",
283                &js4;"$.['store'].['book'][3].['author']",],
284        );
285    }
286
287    #[test]
288    fn descendent_wildcard_test() {
289        let js1 = json!("Moby Dick");
290        let js2 = json!("The Lord of the Rings");
291        test(
292            template_json(),
293            "$..*.[?(@.isbn)].title",
294            jp_v![
295                &js1;"$.['store'].['book'][2].['title']",
296                &js2;"$.['store'].['book'][3].['title']",
297                &js1;"$.['store'].['book'][2].['title']",
298                &js2;"$.['store'].['book'][3].['title']"],
299        );
300    }
301
302    #[test]
303    fn field_test() {
304        let value = json!({"active":1});
305        test(
306            r#"{"field":{"field":[{"active":1},{"passive":1}]}}"#,
307            "$.field.field[?(@.active)]",
308            jp_v![&value;"$.['field'].['field'][0]",],
309        );
310    }
311
312    #[test]
313    fn index_index_test() {
314        let value = json!("0-553-21311-3");
315        test(
316            template_json(),
317            "$..book[2].isbn",
318            jp_v![&value;"$.['store'].['book'][2].['isbn']",],
319        );
320    }
321
322    #[test]
323    fn index_unit_index_test() {
324        let value = json!("0-553-21311-3");
325        test(
326            template_json(),
327            "$..book[2,4].isbn",
328            jp_v![&value;"$.['store'].['book'][2].['isbn']",],
329        );
330        let value1 = json!("0-395-19395-8");
331        test(
332            template_json(),
333            "$..book[2,3].isbn",
334            jp_v![&value;"$.['store'].['book'][2].['isbn']", &value1;"$.['store'].['book'][3].['isbn']",],
335        );
336    }
337
338    #[test]
339    fn index_unit_keys_test() {
340        let js1 = json!("Moby Dick");
341        let js2 = json!(8.99);
342        let js3 = json!("The Lord of the Rings");
343        let js4 = json!(22.99);
344        test(
345            template_json(),
346            "$..book[2,3]['title','price']",
347            jp_v![
348                &js1;"$.['store'].['book'][2].['title']",
349                &js2;"$.['store'].['book'][2].['price']",
350                &js3;"$.['store'].['book'][3].['title']",
351                &js4;"$.['store'].['book'][3].['price']",],
352        );
353    }
354
355    #[test]
356    fn index_slice_test() {
357        let i0 = "$.['array'][0]";
358        let i1 = "$.['array'][1]";
359        let i2 = "$.['array'][2]";
360        let i3 = "$.['array'][3]";
361        let i4 = "$.['array'][4]";
362        let i5 = "$.['array'][5]";
363        let i6 = "$.['array'][6]";
364        let i7 = "$.['array'][7]";
365        let i8 = "$.['array'][8]";
366        let i9 = "$.['array'][9]";
367
368        let j0 = json!(0);
369        let j1 = json!(1);
370        let j2 = json!(2);
371        let j3 = json!(3);
372        let j4 = json!(4);
373        let j5 = json!(5);
374        let j6 = json!(6);
375        let j7 = json!(7);
376        let j8 = json!(8);
377        let j9 = json!(9);
378        test(
379            template_json(),
380            "$.array[:]",
381            jp_v![
382                &j0;&i0,
383                &j1;&i1,
384                &j2;&i2,
385                &j3;&i3,
386                &j4;&i4,
387                &j5;&i5,
388                &j6;&i6,
389                &j7;&i7,
390                &j8;&i8,
391                &j9;&i9,],
392        );
393        test(template_json(), "$.array[1:4:2]", jp_v![&j1;&i1, &j3;&i3,]);
394        test(
395            template_json(),
396            "$.array[::3]",
397            jp_v![&j0;&i0, &j3;&i3, &j6;&i6, &j9;&i9,],
398        );
399        test(template_json(), "$.array[-1:]", jp_v![&j9;&i9,]);
400        test(template_json(), "$.array[-2:-1]", jp_v![&j8;&i8,]);
401    }
402
403    #[test]
404    fn index_filter_test() {
405        let moby = json!("Moby Dick");
406        let rings = json!("The Lord of the Rings");
407        test(
408            template_json(),
409            "$..book[?(@.isbn)].title",
410            jp_v![
411                &moby;"$.['store'].['book'][2].['title']",
412                &rings;"$.['store'].['book'][3].['title']",],
413        );
414        let sword = json!("Sword of Honour");
415        test(
416            template_json(),
417            "$..book[?(@.price != 8.95)].title",
418            jp_v![
419                &sword;"$.['store'].['book'][1].['title']",
420                &moby;"$.['store'].['book'][2].['title']",
421                &rings;"$.['store'].['book'][3].['title']",],
422        );
423        let sayings = json!("Sayings of the Century");
424        test(
425            template_json(),
426            "$..book[?(@.price == 8.95)].title",
427            jp_v![&sayings;"$.['store'].['book'][0].['title']",],
428        );
429        let js895 = json!(8.95);
430        test(
431            template_json(),
432            "$..book[?(@.author ~= '.*Rees')].price",
433            jp_v![&js895;"$.['store'].['book'][0].['price']",],
434        );
435        let js12 = json!(12.99);
436        let js899 = json!(8.99);
437        let js2299 = json!(22.99);
438        test(
439            template_json(),
440            "$..book[?(@.price >= 8.99)].price",
441            jp_v![
442                &js12;"$.['store'].['book'][1].['price']",
443                &js899;"$.['store'].['book'][2].['price']",
444                &js2299;"$.['store'].['book'][3].['price']",
445            ],
446        );
447        test(
448            template_json(),
449            "$..book[?(@.price > 8.99)].price",
450            jp_v![
451                &js12;"$.['store'].['book'][1].['price']",
452                &js2299;"$.['store'].['book'][3].['price']",],
453        );
454        test(
455            template_json(),
456            "$..book[?(@.price < 8.99)].price",
457            jp_v![&js895;"$.['store'].['book'][0].['price']",],
458        );
459        test(
460            template_json(),
461            "$..book[?(@.price <= 8.99)].price",
462            jp_v![
463                &js895;"$.['store'].['book'][0].['price']",
464                &js899;"$.['store'].['book'][2].['price']",
465            ],
466        );
467        test(
468            template_json(),
469            "$..book[?(@.price <= $.expensive)].price",
470            jp_v![
471                &js895;"$.['store'].['book'][0].['price']",
472                &js899;"$.['store'].['book'][2].['price']",
473            ],
474        );
475        test(
476            template_json(),
477            "$..book[?(@.price >= $.expensive)].price",
478            jp_v![
479                &js12;"$.['store'].['book'][1].['price']",
480                &js2299;"$.['store'].['book'][3].['price']",
481            ],
482        );
483        test(
484            template_json(),
485            "$..book[?(@.title in ['Moby Dick','Shmoby Dick','Big Dick','Dicks'])].price",
486            jp_v![&js899;"$.['store'].['book'][2].['price']",],
487        );
488        test(
489            template_json(),
490            "$..book[?(@.title nin ['Moby Dick','Shmoby Dick','Big Dick','Dicks'])].title",
491            jp_v![
492                &sayings;"$.['store'].['book'][0].['title']",
493                &sword;"$.['store'].['book'][1].['title']",
494                &rings;"$.['store'].['book'][3].['title']",],
495        );
496        test(
497            template_json(),
498            "$..book[?(@.author size 10)].title",
499            jp_v![&sayings;"$.['store'].['book'][0].['title']",],
500        );
501        let filled_true = json!(1);
502        test(
503            template_json(),
504            "$.orders[?(@.filled == true)].id",
505            jp_v![&filled_true;"$.['orders'][0].['id']",],
506        );
507        let filled_null = json!(3);
508        test(
509            template_json(),
510            "$.orders[?(@.filled == null)].id",
511            jp_v![&filled_null;"$.['orders'][2].['id']",],
512        );
513    }
514
515    #[test]
516    fn index_filter_sets_test() {
517        let j1 = json!(1);
518        test(
519            template_json(),
520            "$.orders[?(@.ref subsetOf [1,2,3,4])].id",
521            jp_v![&j1;"$.['orders'][0].['id']",],
522        );
523        let j2 = json!(2);
524        test(
525            template_json(),
526            "$.orders[?(@.ref anyOf [1,4])].id",
527            jp_v![&j1;"$.['orders'][0].['id']", &j2;"$.['orders'][1].['id']",],
528        );
529        let j3 = json!(3);
530        test(
531            template_json(),
532            "$.orders[?(@.ref noneOf [3,6])].id",
533            jp_v![&j3;"$.['orders'][2].['id']",],
534        );
535    }
536
537    #[test]
538    fn query_test() {
539        let json: Box<Value> = serde_json::from_str(template_json()).expect("to get json");
540        let v = json
541            .path("$..book[?(@.author size 10)].title")
542            .expect("the path is correct");
543        assert_eq!(v, json!(["Sayings of the Century"]));
544
545        let json: Value = serde_json::from_str(template_json()).expect("to get json");
546        let path = &json
547            .path("$..book[?(@.author size 10)].title")
548            .expect("the path is correct");
549
550        assert_eq!(path, &json!(["Sayings of the Century"]));
551    }
552
553    #[test]
554    fn find_slice_test() {
555        let json: Box<Value> = serde_json::from_str(template_json()).expect("to get json");
556        let path: Box<JsonPath<Value>> = Box::from(
557            JsonPath::try_from("$..book[?(@.author size 10)].title").expect("the path is correct"),
558        );
559        let v = path.find_slice(&json);
560        let js = json!("Sayings of the Century");
561        assert_eq!(v, jp_v![&js;"$.['store'].['book'][0].['title']",]);
562    }
563
564    #[test]
565    fn find_in_array_test() {
566        let json: Box<Value> = Box::new(json!([{"verb": "TEST"}, {"verb": "RUN"}]));
567        let path: Box<JsonPath<Value>> =
568            Box::from(JsonPath::try_from("$.[?(@.verb == 'TEST')]").expect("the path is correct"));
569        let v = path.find_slice(&json);
570        let js = json!({"verb":"TEST"});
571        assert_eq!(v, jp_v![&js;"$[0]",]);
572    }
573
574    #[test]
575    fn length_test() {
576        let json: Box<Value> =
577            Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
578        let path: Box<JsonPath<Value>> = Box::from(
579            JsonPath::try_from("$.[?(@.verb == 'TEST')].length()").expect("the path is correct"),
580        );
581        let v = path.find(&json);
582        let js = json!([2]);
583        assert_eq!(v, js);
584
585        let json: Box<Value> =
586            Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
587        let path: Box<JsonPath<Value>> =
588            Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
589        assert_eq!(path.find(&json), json!([3]));
590
591        // length of search following the wildcard returns correct result
592        let json: Box<Value> =
593            Box::new(json!([{"verb": "TEST"},{"verb": "TEST","x":3}, {"verb": "RUN"}]));
594        let path: Box<JsonPath<Value>> = Box::from(
595            JsonPath::try_from("$.[?(@.verb == 'TEST')].[*].length()")
596                .expect("the path is correct"),
597        );
598        assert_eq!(path.find(&json), json!([3]));
599
600        // length of object returns 0
601        let json: Box<Value> = Box::new(json!({"verb": "TEST"}));
602        let path: Box<JsonPath<Value>> =
603            Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
604        assert_eq!(path.find(&json), Value::Null);
605
606        // length of integer returns null
607        let json: Box<Value> = Box::new(json!(1));
608        let path: Box<JsonPath<Value>> =
609            Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
610        assert_eq!(path.find(&json), Value::Null);
611
612        // length of array returns correct result
613        let json: Box<Value> = Box::new(json!([[1], [2], [3]]));
614        let path: Box<JsonPath<Value>> =
615            Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
616        assert_eq!(path.find(&json), json!([3]));
617
618        // path does not exist returns length null
619        let json: Box<Value> =
620            Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
621        let path: Box<JsonPath<Value>> =
622            Box::from(JsonPath::try_from("$.not.exist.length()").expect("the path is correct"));
623        assert_eq!(path.find(&json), Value::Null);
624
625        // seraching one value returns correct length
626        let json: Box<Value> =
627            Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
628        let path: Box<JsonPath<Value>> = Box::from(
629            JsonPath::try_from("$.[?(@.verb == 'RUN')].length()").expect("the path is correct"),
630        );
631
632        let v = path.find(&json);
633        let js = json!([1]);
634        assert_eq!(v, js);
635
636        // searching correct path following unexisting key returns length 0
637        let json: Box<Value> =
638            Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
639        let path: Box<JsonPath<Value>> = Box::from(
640            JsonPath::try_from("$.[?(@.verb == 'RUN')].key123.length()")
641                .expect("the path is correct"),
642        );
643
644        let v = path.find(&json);
645        let js = json!(null);
646        assert_eq!(v, js);
647
648        // fetching first object returns length null
649        let json: Box<Value> =
650            Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
651        let path: Box<JsonPath<Value>> =
652            Box::from(JsonPath::try_from("$.[0].length()").expect("the path is correct"));
653
654        let v = path.find(&json);
655        let js = Value::Null;
656        assert_eq!(v, js);
657
658        // length on fetching the index after search gives length of the object (array)
659        let json: Box<Value> = Box::new(json!([{"prop": [["a", "b", "c"], "d"]}]));
660        let path: Box<JsonPath<Value>> = Box::from(
661            JsonPath::try_from("$.[?(@.prop)].prop.[0].length()").expect("the path is correct"),
662        );
663
664        let v = path.find(&json);
665        let js = json!([3]);
666        assert_eq!(v, js);
667
668        // length on fetching the index after search gives length of the object (string)
669        let json: Box<Value> = Box::new(json!([{"prop": [["a", "b", "c"], "d"]}]));
670        let path: Box<JsonPath<Value>> = Box::from(
671            JsonPath::try_from("$.[?(@.prop)].prop.[1].length()").expect("the path is correct"),
672        );
673
674        let v = path.find(&json);
675        let js = Value::Null;
676        assert_eq!(v, js);
677    }
678
679    #[test]
680    fn no_value_index_from_not_arr_filter_test() {
681        let json: Box<Value> = Box::new(json!({
682            "field":"field",
683        }));
684
685        let path: Box<JsonPath<Value>> =
686            Box::from(JsonPath::try_from("$.field[1]").expect("the path is correct"));
687        let v = path.find_slice(&json);
688        assert_eq!(v, vec![NoValue]);
689
690        let json: Box<Value> = Box::new(json!({
691            "field":[0],
692        }));
693
694        let path: Box<JsonPath<Value>> =
695            Box::from(JsonPath::try_from("$.field[1]").expect("the path is correct"));
696        let v = path.find_slice(&json);
697        assert_eq!(v, vec![NoValue]);
698    }
699
700    #[test]
701    fn no_value_filter_from_not_arr_filter_test() {
702        let json: Box<Value> = Box::new(json!({
703            "field":"field",
704        }));
705
706        let path: Box<JsonPath<Value>> =
707            Box::from(JsonPath::try_from("$.field[?(@ == 0)]").expect("the path is correct"));
708        let v = path.find_slice(&json);
709        assert_eq!(v, vec![NoValue]);
710    }
711
712    #[test]
713    fn no_value_index_filter_test() {
714        let json: Box<Value> = Box::new(json!({
715            "field":[{"f":1},{"f":0}],
716        }));
717
718        let path: Box<JsonPath<Value>> =
719            Box::from(JsonPath::try_from("$.field[?(@.f_ == 0)]").expect("the path is correct"));
720        let v = path.find_slice(&json);
721        assert_eq!(v, vec![NoValue]);
722    }
723
724    #[test]
725    fn no_value_decent_test() {
726        let json: Box<Value> = Box::new(json!({
727            "field":[{"f":1},{"f":{"f_":1}}],
728        }));
729
730        let path: Box<JsonPath<Value>> =
731            Box::from(JsonPath::try_from("$..f_").expect("the path is correct"));
732        let v = path.find_slice(&json);
733        assert_eq!(
734            v,
735            vec![Slice(&json!(1), "$.['field'][1].['f'].['f_']".to_string())]
736        );
737    }
738
739    #[test]
740    fn no_value_chain_test() {
741        let json: Box<Value> = Box::new(json!({
742            "field":{"field":[1]},
743        }));
744
745        let path: Box<JsonPath<Value>> =
746            Box::from(JsonPath::try_from("$.field_.field").expect("the path is correct"));
747        let v = path.find_slice(&json);
748        assert_eq!(v, vec![NoValue]);
749
750        let path: Box<JsonPath<Value>> = Box::from(
751            JsonPath::try_from("$.field_.field[?(@ == 1)]").expect("the path is correct"),
752        );
753        let v = path.find_slice(&json);
754        assert_eq!(v, vec![NoValue]);
755    }
756
757    #[test]
758    fn no_value_filter_test() {
759        // searching unexisting value returns length 0
760        let json: Box<Value> =
761            Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
762        let path: Box<JsonPath<Value>> = Box::from(
763            JsonPath::try_from("$.[?(@.verb == \"RUN1\")]").expect("the path is correct"),
764        );
765        let v = path.find(&json);
766        let js = json!(null);
767        assert_eq!(v, js);
768    }
769
770    #[test]
771    fn no_value_len_test() {
772        let json: Box<Value> = Box::new(json!({
773            "field":{"field":1},
774        }));
775
776        let path: Box<JsonPath<Value>> =
777            Box::from(JsonPath::try_from("$.field.field.length()").expect("the path is correct"));
778        let v = path.find_slice(&json);
779        assert_eq!(v, vec![NoValue]);
780
781        let json: Box<Value> = Box::new(json!({
782            "field":[{"a":1},{"a":1}],
783        }));
784        let path: Box<JsonPath<Value>> = Box::from(
785            JsonPath::try_from("$.field[?(@.a == 0)].f.length()").expect("the path is correct"),
786        );
787        let v = path.find_slice(&json);
788        assert_eq!(v, vec![NoValue]);
789    }
790
791    #[test]
792    fn no_clone_api_test() {
793        fn test_coercion(value: &Value) -> Value {
794            value.clone()
795        }
796
797        let json: Value = serde_json::from_str(template_json()).expect("to get json");
798        let query =
799            JsonPath::try_from("$..book[?(@.author size 10)].title").expect("the path is correct");
800
801        let results = query.find_slice_ptr(&json);
802        let v = results.first().expect("to get value");
803
804        // V can be implicitly converted to &Value
805        test_coercion(v);
806
807        // To explicitly convert to &Value, use deref()
808        assert_eq!(v.deref(), &json!("Sayings of the Century"));
809    }
810
811    #[test]
812    fn logical_exp_test() {
813        let json: Box<Value> = Box::new(json!({"first":{"second":[{"active":1},{"passive":1}]}}));
814
815        let path: Box<JsonPath<Value>> = Box::from(
816            JsonPath::try_from("$.first[?(@.does_not_exist && @.does_not_exist >= 1.0)]")
817                .expect("the path is correct"),
818        );
819        let v = path.find_slice(&json);
820        assert_eq!(v, vec![NoValue]);
821
822        let path: Box<JsonPath<Value>> = Box::from(
823            JsonPath::try_from("$.first[?(@.does_not_exist >= 1.0)]").expect("the path is correct"),
824        );
825        let v = path.find_slice(&json);
826        assert_eq!(v, vec![NoValue]);
827    }
828
829    #[test]
830    fn regex_filter_test() {
831        let json: Box<Value> = Box::new(json!({
832            "author":"abcd(Rees)",
833        }));
834
835        let path: Box<JsonPath<Value>> = Box::from(
836            JsonPath::try_from("$.[?(@.author ~= '(?i)d\\(Rees\\)')]")
837                .expect("the path is correct"),
838        );
839        assert_eq!(
840            path.find_slice(&json.clone()),
841            vec![Slice(&json!({"author":"abcd(Rees)"}), "$".to_string())]
842        );
843    }
844
845    #[test]
846    fn logical_not_exp_test() {
847        let json: Box<Value> = Box::new(json!({"first":{"second":{"active":1}}}));
848        let path: Box<JsonPath<Value>> = Box::from(
849            JsonPath::try_from("$.first[?(!@.does_not_exist >= 1.0)]")
850                .expect("the path is correct"),
851        );
852        let v = path.find_slice(&json);
853        assert_eq!(
854            v,
855            vec![Slice(
856                &json!({"second":{"active": 1}}),
857                "$.['first']".to_string()
858            )]
859        );
860
861        let path: Box<JsonPath<Value>> = Box::from(
862            JsonPath::try_from("$.first[?(!(@.does_not_exist >= 1.0))]")
863                .expect("the path is correct"),
864        );
865        let v = path.find_slice(&json);
866        assert_eq!(
867            v,
868            vec![Slice(
869                &json!({"second":{"active": 1}}),
870                "$.['first']".to_string()
871            )]
872        );
873
874        let path: Box<JsonPath<Value>> = Box::from(
875            JsonPath::try_from("$.first[?(!(@.second.active == 1) || @.second.active == 1)]")
876                .expect("the path is correct"),
877        );
878        let v = path.find_slice(&json);
879        assert_eq!(
880            v,
881            vec![Slice(
882                &json!({"second":{"active": 1}}),
883                "$.['first']".to_string()
884            )]
885        );
886
887        let path: Box<JsonPath<Value>> = Box::from(
888            JsonPath::try_from("$.first[?(!@.second.active == 1 && !@.second.active == 1 || !@.second.active == 2)]")
889                .expect("the path is correct"),
890        );
891        let v = path.find_slice(&json);
892        assert_eq!(
893            v,
894            vec![Slice(
895                &json!({"second":{"active": 1}}),
896                "$.['first']".to_string()
897            )]
898        );
899    }
900
901    #[test]
902    fn update_by_path_test() -> Result<(), JsonPathParserError> {
903        let mut json = json!([
904            {"verb": "RUN","distance":[1]},
905            {"verb": "TEST"},
906            {"verb": "DO NOT RUN"}
907        ]);
908
909        let path: Box<JsonPath> = Box::from(JsonPath::try_from("$.[?(@.verb == 'RUN')]")?);
910        let elem = path
911            .find_as_path(&json)
912            .first()
913            .cloned()
914            .ok_or(JsonPathParserError::InvalidJsonPath("".to_string()))?;
915
916        if let Some(v) = json
917            .reference_mut(elem)?
918            .and_then(|v| v.as_object_mut())
919            .and_then(|v| v.get_mut("distance"))
920            .and_then(|v| v.as_array_mut())
921        {
922            v.push(json!(2))
923        }
924
925        assert_eq!(
926            json,
927            json!([
928                {"verb": "RUN","distance":[1,2]},
929                {"verb": "TEST"},
930                {"verb": "DO NOT RUN"}
931            ])
932        );
933
934        Ok(())
935    }
936}