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