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