1mod atom;
2mod comparable;
3mod comparison;
4mod filter;
5mod jp_query;
6pub mod queryable;
7mod segment;
8mod selector;
9pub mod state;
10mod test;
11mod test_function;
12
13use crate::parser::errors::JsonPathError;
14use crate::parser::model::JpQuery;
15use crate::parser::{parse_json_path, Parsed};
16use crate::query::queryable::Queryable;
17use crate::query::state::{Data, Pointer};
18use state::State;
19use std::borrow::Cow;
20
21pub type QueryPath = String;
23
24pub type Queried<T> = Result<T, JsonPathError>;
26
27pub trait Query {
29 fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T>;
30}
31
32#[derive(Debug, Clone, PartialEq)]
35pub struct QueryRef<'a, T: Queryable> {
36 pub val: &'a T,
37 pub path: QueryPath,
38}
39
40impl<'a, T: Queryable> QueryRef<'a, T> {
41 pub fn val(self) -> &'a T {
42 self.val
43 }
44 pub fn path(self) -> QueryPath {
45 self.path
46 }
47}
48
49impl<'a, T: Queryable> From<(&'a T, QueryPath)> for QueryRef<'a, T> {
50 fn from((val, path): (&'a T, QueryPath)) -> Self {
51 QueryRef { val, path }
52 }
53}
54impl<'a, T: Queryable> From<(&'a T, &str)> for QueryRef<'a, T> {
55 fn from((val, path): (&'a T, &str)) -> Self {
56 QueryRef {
57 val,
58 path: path.to_string(),
59 }
60 }
61}
62
63impl<'a, T: Queryable> From<Pointer<'a, T>> for QueryRef<'a, T> {
64 fn from(pointer: Pointer<'a, T>) -> Self {
65 QueryRef {
66 val: pointer.inner,
67 path: pointer.path,
68 }
69 }
70}
71
72pub fn js_path<'a, T: Queryable>(path: &str, value: &'a T) -> Queried<Vec<QueryRef<'a, T>>> {
75 js_path_process(&parse_json_path(path)?, value)
76}
77
78pub fn js_path_process<'a, 'b, T: Queryable>(
81 path: &'b JpQuery,
82 value: &'a T,
83) -> Queried<Vec<QueryRef<'a, T>>> {
84 match path.process(State::root(value)).data {
85 Data::Ref(p) => Ok(vec![p.into()]),
86 Data::Refs(refs) => Ok(refs.into_iter().map(Into::into).collect()),
87 Data::Value(v) => Err(v.into()),
88 Data::Nothing => Ok(vec![]),
89 }
90}
91
92pub fn js_path_vals<'a, T: Queryable>(path: &str, value: &'a T) -> Queried<Vec<&'a T>> {
94 Ok(js_path(path, value)?
95 .into_iter()
96 .map(|r| r.val)
97 .collect::<Vec<_>>())
98}
99
100pub fn js_path_path<T: Queryable>(path: &str, value: &T) -> Queried<Vec<QueryPath>> {
102 Ok(js_path(path, value)?
103 .into_iter()
104 .map(|r| r.path)
105 .collect::<Vec<_>>())
106}
107
108#[cfg(test)]
109mod tests {
110 use crate::parser::errors::JsonPathError;
111 use crate::parser::{parse_json_path, Parsed};
112 use crate::query::queryable::Queryable;
113 use crate::query::{js_path, js_path_process, Queried, QueryRef};
114 use crate::JsonPath;
115 use serde_json::{json, Value};
116
117 fn test<'a, R>(json: &'a str, path: &str, expected: Vec<R>) -> Parsed<()>
118 where
119 R: Into<QueryRef<'a, Value>>,
120 {
121 let json: Value = serde_json::from_str(json).map_err(|v| JsonPathError::NoRulePath)?;
122 let expected: Vec<QueryRef<'a, Value>> = expected.into_iter().map(|v| v.into()).collect();
123 assert_eq!(json.query_with_path(path)?, expected);
124
125 Ok(())
126 }
127
128 fn template_json<'a>() -> &'a str {
129 r#" {"store": { "book": [
130 {
131 "category": "reference",
132 "author": "Nigel Rees",
133 "title": "Sayings of the Century",
134 "price": 8.95
135 },
136 {
137 "category": "fiction",
138 "author": "Evelyn Waugh",
139 "title": "Sword of Honour",
140 "price": 12.99
141 },
142 {
143 "category": "fiction",
144 "author": "Herman Melville",
145 "title": "Moby Dick",
146 "isbn": "0-553-21311-3",
147 "price": 8.99
148 },
149 {
150 "category": "fiction",
151 "author": "J. R. R. Tolkien",
152 "title": "The Lord of the Rings",
153 "isbn": "0-395-19395-8",
154 "price": 22.99
155 }
156 ],
157 "bicycle": {
158 "color": "red",
159 "price": 19.95
160 }
161 },
162 "array":[0,1,2,3,4,5,6,7,8,9],
163 "orders":[
164 {
165 "ref":[1,2,3],
166 "id":1,
167 "filled": true
168 },
169 {
170 "ref":[4,5,6],
171 "id":2,
172 "filled": false
173 },
174 {
175 "ref":[7,8,9],
176 "id":3,
177 "filled": null
178 }
179 ],
180 "expensive": 10 }"#
181 }
182
183 #[test]
184 fn update_by_path_test() -> Queried<()> {
185 let mut json = json!([
186 {"verb": "RUN","distance":[1]},
187 {"verb": "TEST"},
188 {"verb": "DO NOT RUN"}
189 ]);
190
191 let path = json.query_only_path("$[?(@.verb == 'RUN')]")?;
192 let elem = path.first().cloned().unwrap_or_default();
193
194 if let Some(v) = json
195 .reference_mut(elem)
196 .and_then(|v| v.as_object_mut())
197 .and_then(|v| v.get_mut("distance"))
198 .and_then(|v| v.as_array_mut())
199 {
200 v.push(json!(2))
201 }
202
203 assert_eq!(
204 json,
205 json!([
206 {"verb": "RUN","distance":[1,2]},
207 {"verb": "TEST"},
208 {"verb": "DO NOT RUN"}
209 ])
210 );
211
212 Ok(())
213 }
214
215 #[test]
216 fn simple_test() {
217 let j1 = json!(2);
218 let _ = test("[1,2,3]", "$[1]", vec![(&j1, "$[1]".to_string())]);
219 }
220
221 #[test]
222 fn root_test() {
223 let js = serde_json::from_str(template_json()).unwrap();
224 let _ = test(template_json(), "$", vec![(&js, "$")]);
225 }
226
227 #[test]
228 fn descent_test() {
229 let v1 = json!("reference");
230 let v2 = json!("fiction");
231 let _ = test(
232 template_json(),
233 "$..category",
234 vec![
235 (&v1, "$['store']['book'][0]['category']"),
236 (&v2, "$['store']['book'][1]['category']"),
237 (&v2, "$['store']['book'][2]['category']"),
238 (&v2, "$['store']['book'][3]['category']"),
239 ],
240 );
241 let js1 = json!(19.95);
242 let js2 = json!(8.95);
243 let js3 = json!(12.99);
244 let js4 = json!(8.99);
245 let js5 = json!(22.99);
246 let _ = test(
247 template_json(),
248 "$.store..price",
249 vec![
250 (&js1, "$['store']['bicycle']['price']"),
251 (&js2, "$['store']['book'][0]['price']"),
252 (&js3, "$['store']['book'][1]['price']"),
253 (&js4, "$['store']['book'][2]['price']"),
254 (&js5, "$['store']['book'][3]['price']"),
255 ],
256 );
257 let js1 = json!("Nigel Rees");
258 let js2 = json!("Evelyn Waugh");
259 let js3 = json!("Herman Melville");
260 let js4 = json!("J. R. R. Tolkien");
261 let _ = test(
262 template_json(),
263 "$..author",
264 vec![
265 (&js1, "$['store']['book'][0]['author']"),
266 (&js2, "$['store']['book'][1]['author']"),
267 (&js3, "$['store']['book'][2]['author']"),
268 (&js4, "$['store']['book'][3]['author']"),
269 ],
270 );
271 }
272
273 #[test]
274 fn wildcard_test() {
275 let js1 = json!("reference");
276 let js2 = json!("fiction");
277 let _ = test(
278 template_json(),
279 "$..book.[*].category",
280 vec![
281 (&js1, "$['store']['book'][0].['category']"),
282 (&js2, "$['store']['book'][1].['category']"),
283 (&js2, "$['store']['book'][2].['category']"),
284 (&js2, "$['store']['book'][3].['category']"),
285 ],
286 );
287 let js1 = json!("Nigel Rees");
288 let js2 = json!("Evelyn Waugh");
289 let js3 = json!("Herman Melville");
290 let js4 = json!("J. R. R. Tolkien");
291 let _ = test(
292 template_json(),
293 "$.store.book[*].author",
294 vec![
295 (&js1, "$['store']['book'][0]['author']"),
296 (&js2, "$['store']['book'][1]['author']"),
297 (&js3, "$['store']['book'][2]['author']"),
298 (&js4, "$['store']['book'][3]['author']"),
299 ],
300 );
301 }
302
303 #[test]
304 fn descendent_wildcard_test() {
305 let js1 = json!("0-553-21311-3");
306 let js2 = json!("0-395-19395-8");
307 let _ = test(
308 template_json(),
309 "$..*.[?@].isbn",
310 vec![
311 (&js1, "$['store']['book'][2]['isbn']"),
312 (&js2, "$['store']['book'][3]['isbn']"),
313 ],
314 );
315 }
316
317 #[test]
318 fn field_test() {
319 let value = json!({"active":1});
320 let _ = test(
321 r#"{"field":{"field":[{"active":1},{"passive":1}]}}"#,
322 "$.field.field[?@.active]",
323 vec![(&value, "$['field']['field'][0]")],
324 );
325 }
326
327 #[test]
328 fn index_index_test() {
329 let value = json!("0-553-21311-3");
330 let _ = test(
331 template_json(),
332 "$..book[2].isbn",
333 vec![(&value, "$['store']['book'][2]['isbn']")],
334 );
335 }
336
337 #[test]
338 fn index_unit_index_test() {
339 let value = json!("0-553-21311-3");
340 let _ = test(
341 template_json(),
342 "$..book[2,4].isbn",
343 vec![(&value, "$['store']['book'][2]['isbn']")],
344 );
345 let value1 = json!("0-395-19395-8");
346 let _ = test(
347 template_json(),
348 "$..book[2,3].isbn",
349 vec![
350 (&value, "$['store']['book'][2]['isbn']"),
351 (&value1, "$['store']['book'][3]['isbn']"),
352 ],
353 );
354 }
355
356 #[test]
357 fn index_unit_keys_test() {
358 let js1 = json!("Moby Dick");
359 let js2 = json!(8.99);
360 let js3 = json!("The Lord of the Rings");
361 let js4 = json!(22.99);
362 let _ = test(
363 template_json(),
364 "$..book[2,3]['title','price']",
365 vec![
366 (&js1, "$['store']['book'][2]['title']"),
367 (&js3, "$['store']['book'][3]['title']"),
368 (&js2, "$['store']['book'][2]['price']"),
369 (&js4, "$['store']['book'][3]['price']"),
370 ],
371 );
372 }
373
374 #[test]
375 fn index_slice_test() -> Parsed<()> {
376 let i0 = "$['array'][0]";
377 let i1 = "$['array'][1]";
378 let i2 = "$['array'][2]";
379 let i3 = "$['array'][3]";
380 let i4 = "$['array'][4]";
381 let i5 = "$['array'][5]";
382 let i6 = "$['array'][6]";
383 let i7 = "$['array'][7]";
384 let i8 = "$['array'][8]";
385 let i9 = "$['array'][9]";
386
387 let j0 = json!(0);
388 let j1 = json!(1);
389 let j2 = json!(2);
390 let j3 = json!(3);
391 let j4 = json!(4);
392 let j5 = json!(5);
393 let j6 = json!(6);
394 let j7 = json!(7);
395 let j8 = json!(8);
396 let j9 = json!(9);
397 test(
398 template_json(),
399 "$.array[:]",
400 vec![
401 (&j0, i0),
402 (&j1, i1),
403 (&j2, i2),
404 (&j3, i3),
405 (&j4, i4),
406 (&j5, i5),
407 (&j6, i6),
408 (&j7, i7),
409 (&j8, i8),
410 (&j9, i9),
411 ],
412 )?;
413 test(
414 template_json(),
415 "$.array[1:4:2]",
416 vec![(&j1, i1), (&j3, i3)],
417 )?;
418 test(
419 template_json(),
420 "$.array[::3]",
421 vec![(&j0, i0), (&j3, i3), (&j6, i6), (&j9, i9)],
422 )?;
423 test(template_json(), "$.array[-1:]", vec![(&j9, i9)])?;
424 test(template_json(), "$.array[-2:-1]", vec![(&j8, i8)])?;
425
426 Ok(())
427 }
428
429 #[test]
430 fn index_filter_test() -> Parsed<()> {
431 let moby = json!("Moby Dick");
432 let rings = json!("The Lord of the Rings");
433 test(
434 template_json(),
435 "$..book[?@.isbn].title",
436 vec![
437 (&moby, "$['store']['book'][2]['title']"),
438 (&rings, "$['store']['book'][3]['title']"),
439 ],
440 )?;
441 let sword = json!("Sword of Honour");
442 test(
443 template_json(),
444 "$..book[?(@.price != 8.95)].title",
445 vec![
446 (&sword, "$['store']['book'][1]['title']"),
447 (&moby, "$['store']['book'][2]['title']"),
448 (&rings, "$['store']['book'][3]['title']"),
449 ],
450 )?;
451 let sayings = json!("Sayings of the Century");
452 test(
453 template_json(),
454 "$..book[?(@.price == 8.95)].title",
455 vec![(&sayings, "$['store']['book'][0]['title']")],
456 )?;
457
458 let js12 = json!(12.99);
459 let js899 = json!(8.99);
460 let js2299 = json!(22.99);
461 test(
462 template_json(),
463 "$..book[?@.price >= 8.99].price",
464 vec![
465 (&js12, "$['store']['book'][1]['price']"),
466 (&js899, "$['store']['book'][2]['price']"),
467 (&js2299, "$['store']['book'][3]['price']"),
468 ],
469 )?;
470
471 test(
472 template_json(),
473 "$..book[?(@.price >= $.expensive)].price",
474 vec![
475 (&js12, "$['store']['book'][1]['price']"),
476 (&js2299, "$['store']['book'][3]['price']"),
477 ],
478 )?;
479 Ok(())
480 }
481
482 #[test]
483 fn union_quotes() -> Queried<()> {
484 let json = json!({
485 "a": "ab",
486 "b": "bc"
487 });
488
489 let vec = js_path("$['a',\r'b']", &json)?;
490
491 assert_eq!(
492 vec,
493 vec![
494 (&json!("ab"), "$['a']".to_string()).into(),
495 (&json!("bc"), "$['b']".to_string()).into(),
496 ]
497 );
498
499 Ok(())
500 }
501
502 #[test]
503 fn space_between_selectors() -> Queried<()> {
504 let json = json!({
505 "a": {
506 "b": "ab"
507 }
508 });
509
510 let vec = js_path("$['a'] \r['b']", &json)?;
511
512 assert_eq!(vec, vec![(&json!("ab"), "$['a']['b']".to_string()).into(),]);
513
514 Ok(())
515 }
516 #[test]
517 fn space_in_search() -> Queried<()> {
518 let json = json!(["foo", "123"]);
519
520 let vec = js_path("$[?search(@\n,'[a-z]+')]", &json)?;
521
522 assert_eq!(vec, vec![(&json!("foo"), "$[0]".to_string()).into(),]);
523
524 Ok(())
525 }
526 #[test]
527 fn filter_key() -> Queried<()> {
528 let json = json!([
529 {
530 "a": "b",
531 "d": "e"
532 },
533 {
534 "a": 1,
535 "d": "f"
536 }
537 ]);
538
539 let vec = js_path("$[?@.a!=\"b\"]", &json)?;
540
541 assert_eq!(
542 vec,
543 vec![(&json!({"a":1, "d":"f"}), "$[1]".to_string()).into(),]
544 );
545
546 Ok(())
547 }
548
549 #[test]
550 fn regex_key() -> Queried<()> {
551 let json = json!({
552 "regex": "b.?b",
553 "values": [
554 "abc",
555 "bcd",
556 "bab",
557 "bba",
558 "bbab",
559 "b",
560 true,
561 [],
562 {}
563 ]
564 });
565
566 let vec = js_path("$.values[?match(@, $.regex)]", &json)?;
567
568 assert_eq!(
569 vec,
570 vec![(&json!("bab"), "$['values'][2]".to_string()).into(),]
571 );
572
573 Ok(())
574 }
575 #[test]
576 fn name_sel() -> Queried<()> {
577 let json = json!({
578 "/": "A"
579 });
580
581 let vec = js_path("$['\\/']", &json)?;
582
583 assert_eq!(vec, vec![(&json!("A"), "$['\\/']".to_string()).into(),]);
584
585 Ok(())
586 }
587 #[test]
588 fn unicode_fns() -> Queried<()> {
589 let json = json!(["ж", "Ж", "1", "жЖ", true, [], {}]);
590
591 let vec = js_path("$[?match(@, '\\\\p{Lu}')]", &json)?;
592
593 assert_eq!(vec, vec![(&json!("Ж"), "$[1]".to_string()).into(),]);
594
595 Ok(())
596 }
597 #[test]
598 fn fn_res_can_not_compare() -> Queried<()> {
599 let json = json!({});
600
601 let vec = js_path("$[?match(@.a, 'a.*')==true]", &json);
602
603 assert!(vec.is_err());
604
605 Ok(())
606 }
607 #[test]
608 fn too_small() -> Queried<()> {
609 let json = json!({});
610
611 let vec = js_path("$[-9007199254740992]", &json);
612
613 assert!(vec.is_err());
614
615 Ok(())
616 }
617 #[test]
618 fn filter_data() -> Queried<()> {
619 let json = json!({
620 "a": 1,
621 "b": 2,
622 "c": 3
623 });
624
625 let vec: Vec<String> = json.query_only_path("$[?@<3]")?.into_iter().collect();
626
627 assert_eq!(vec, vec!["$['a']".to_string(), "$['b']".to_string()]);
628
629 Ok(())
630 }
631 #[test]
632 fn exp_no_error() -> Queried<()> {
633 let json = json!([
634 {
635 "a": 100,
636 "d": "e"
637 },
638 {
639 "a": 100.1,
640 "d": "f"
641 },
642 {
643 "a": "100",
644 "d": "g"
645 }
646 ]);
647
648 let vec: Vec<&Value> = json.query("$[?@.a==1E2]")?;
649 assert_eq!(vec, vec![&json!({"a":100, "d":"e"})]);
650
651 Ok(())
652 }
653 #[test]
654 fn single_quote() -> Queried<()> {
655 let json = json!({
656 "a'": "A",
657 "b": "B"
658 });
659
660 let vec = js_path("$[\"a'\"]", &json)?;
661 assert_eq!(vec, vec![(&json!("A"), "$['\"a\'\"']".to_string()).into(),]);
662
663 Ok(())
664 }
665 #[test]
666 fn union() -> Queried<()> {
667 let json = json!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
668
669 let vec: Vec<QueryRef<Value>> = json.query_with_path("$[1,5:7]")?;
670 assert_eq!(
671 vec,
672 vec![
673 (&json!(1), "$[1]".to_string()).into(),
674 (&json!(5), "$[5]".to_string()).into(),
675 (&json!(6), "$[6]".to_string()).into(),
676 ]
677 );
678
679 Ok(())
680 }
681
682 #[test]
683 fn basic_descendent() -> Queried<()> {
684 let json = json!({
685 "o": [
686 0,
687 1,
688 [
689 2,
690 3
691 ]
692 ]
693 });
694
695 let vec = js_path("$..[1]", &json)?;
696 assert_eq!(
697 vec,
698 vec![
699 (&json!(1), "$['o'][1]".to_string()).into(),
700 (&json!(3), "$['o'][2][1]".to_string()).into(),
701 ]
702 );
703
704 Ok(())
705 }
706 #[test]
707 fn filter_absent() -> Queried<()> {
708 let json = json!([
709 {
710 "list": [
711 1
712 ]
713 }
714 ]);
715
716 let vec = js_path("$[?@.absent==@.list[9]]", &json)?;
717 assert_eq!(
718 vec,
719 vec![(&json!({"list": [1]}), "$[0]".to_string()).into(),]
720 );
721
722 Ok(())
723 }
724
725 #[test]
726 fn filter_star() -> Queried<()> {
727 let json = json!([1,[],[2],{},{"a": 3}]);
728
729 let vec = json.query_with_path("$[?@.*]")?;
730 assert_eq!(
731 vec,
732 vec![
733 (&json!([2]), "$[2]".to_string()).into(),
734 (&json!({"a": 3}), "$[4]".to_string()).into(),
735 ]
736 );
737
738 Ok(())
739 }
740
741 #[test]
742 fn space_test() -> Queried<()> {
743 let json = json!({ " ": "A"});
744
745 let vec = json.query_with_path("$[' ']")?;
746 assert_eq!(vec, vec![(&json!("A"), "$[\' \']".to_string()).into(),]);
747
748 Ok(())
749 }
750 #[test]
751 fn neg_idx() -> Queried<()> {
752 let json = json!(["first", "second"]);
753
754 let vec = json.query_with_path("$[-2]")?;
755 assert_eq!(vec, vec![(&json!("first"), "$[0]".to_string()).into(),]);
756
757 Ok(())
758 }
759
760 #[test]
761 fn filter_slice() -> Queried<()> {
762 let json = json!([
763 1,
764 [],
765 [
766 2
767 ],
768 [
769 2,
770 3,
771 4
772 ],
773 {},
774 {
775 "a": 3
776 }
777 ]);
778
779 let vec = json.query_with_path("$[?@[0:2]]")?;
780 assert_eq!(
781 vec,
782 vec![
783 (&json!([2]), "$[2]").into(),
784 (&json!([2, 3, 4]), "$[3]").into(),
785 ]
786 );
787
788 Ok(())
789 }
790
791 #[test]
792 fn surr_pairs() -> Queried<()> {
793 let json = json!({
794 "𝄞": "A"
795 });
796 let vec = json.query_with_path("$['𝄞']")?;
797 assert_eq!(vec, vec![(&json!("A"), "$['𝄞']".to_string()).into()]);
798
799 Ok(())
800 }
801 #[test]
802 fn tab_key() -> Queried<()> {
803 let json = json!({
804 "\\t": "A"
805 });
806 let vec = json.query_with_path("$['\\t']")?;
807 assert_eq!(vec, vec![(&json!("A"), "$['\\t']".to_string()).into()]);
808
809 Ok(())
810 }
811 #[test]
812 fn escaped_up_hex() -> Queried<()> {
813 let json = json!({
814 "☺": "A"
815 });
816 let vec = json.query_with_path("$['☺']")?;
817 assert_eq!(vec, vec![(&json!("A"), "$['☺']".to_string()).into()]);
818
819 Ok(())
820 }
821 #[test]
822 fn carr_return() -> Queried<()> {
823 let json = json!({
824 "\\r": "A"
825 });
826 let vec = json.query_with_path("$['\\r']")?;
827 assert_eq!(vec, vec![(&json!("A"), "$['\\r']".to_string()).into()]);
828
829 Ok(())
830 }
831
832 #[test]
833 fn prepared_query() -> Queried<()> {
834 let json1 = json!({
835 "a": 1,
836 "b": 2,
837 "c": 3
838 });
839 let json2 = json!({
840 "a": 1,
841 "b": 2,
842 "c": 3
843 });
844
845 let jq = parse_json_path("$[?@<3]")?;
846
847 let v1 = js_path_process(&jq, &json1)?;
848 let v2 = js_path_process(&jq, &json2)?;
849
850 assert_eq!(v1, v2);
851
852 Ok(())
853 }
854}