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