Skip to content

Commit 5467b2d

Browse files
authored
Add JsonLike trait (#74)
* chore: expose jsonlike trait * chore: add JsonLike trait * chore: make clippy happy * chore: fix by pr comment * chore: remove path json * chore :add doc for JsonLike trait
1 parent c529399 commit 5467b2d

File tree

10 files changed

+1015
-698
lines changed

10 files changed

+1015
-698
lines changed

benches/regex.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use criterion::{criterion_group, criterion_main, Criterion};
22
use jsonpath_rust::{JsonPath, JsonPathQuery};
3-
use serde_json::json;
3+
use serde_json::{json, Value};
44
use std::str::FromStr;
55

66
struct SearchData {
@@ -23,7 +23,7 @@ fn regex_perf_test_without_reuse() {
2323
}
2424

2525
fn json_path_compiling() {
26-
let _v = JsonPath::from_str(PATH).unwrap();
26+
let _v = JsonPath::<Value>::from_str(PATH).unwrap();
2727
}
2828

2929
pub fn criterion_benchmark(c: &mut Criterion) {

src/jsonpath.rs

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use crate::path::json_path_instance;
2+
use crate::path::JsonLike;
23
use crate::JsonPath;
34
use crate::JsonPathValue;
45
use crate::JsonPathValue::NoValue;
56
use crate::JsonPtr;
6-
use crate::Value;
77

8-
impl JsonPath {
8+
impl<T> JsonPath<T>
9+
where
10+
T: JsonLike,
11+
{
912
/// finds a slice of data in the set json.
1013
/// The result is a vector of references to the incoming structure.
1114
///
@@ -29,12 +32,11 @@ impl JsonPath {
2932
/// vec![JsonPathValue::Slice(&expected_value, expected_path)]
3033
/// );
3134
/// ```
32-
pub fn find_slice<'a>(&'a self, json: &'a Value) -> Vec<JsonPathValue<'a, Value>> {
35+
pub fn find_slice<'a>(&'a self, json: &'a T) -> Vec<JsonPathValue<'a, T>> {
3336
use crate::path::Path;
3437
let instance = json_path_instance(self, json);
3538
let res = instance.find(JsonPathValue::from_root(json));
36-
let has_v: Vec<JsonPathValue<'_, Value>> =
37-
res.into_iter().filter(|v| v.has_value()).collect();
39+
let has_v: Vec<JsonPathValue<'_, T>> = res.into_iter().filter(|v| v.has_value()).collect();
3840

3941
if has_v.is_empty() {
4042
vec![NoValue]
@@ -45,7 +47,7 @@ impl JsonPath {
4547

4648
/// like [`Self::find_slice`] but returns a vector of [`JsonPtr`], which has no [`JsonPathValue::NoValue`].
4749
/// if there is no match, it will return an empty vector
48-
pub fn find_slice_ptr<'a>(&'a self, json: &'a Value) -> Vec<JsonPtr<'a, Value>> {
50+
pub fn find_slice_ptr<'a>(&'a self, json: &'a T) -> Vec<JsonPtr<'a, T>> {
4951
use crate::path::Path;
5052
json_path_instance(self, json)
5153
.find(JsonPathValue::from_root(json))
@@ -76,13 +78,13 @@ impl JsonPath {
7678
///
7779
/// assert_eq!(cloned_data, Value::Array(vec![json!({"active":1})]));
7880
/// ```
79-
pub fn find(&self, json: &Value) -> Value {
81+
pub fn find(&self, json: &T) -> T {
8082
let slice = self.find_slice(json);
8183
if !slice.is_empty() {
8284
if JsonPathValue::only_no_value(&slice) {
83-
Value::Null
85+
T::null()
8486
} else {
85-
Value::Array(
87+
T::array(
8688
slice
8789
.into_iter()
8890
.filter(|v| v.has_value())
@@ -91,7 +93,7 @@ impl JsonPath {
9193
)
9294
}
9395
} else {
94-
Value::Array(vec![])
96+
T::array(vec![])
9597
}
9698
}
9799

@@ -114,8 +116,8 @@ impl JsonPath {
114116
/// let expected_path = "$.['first'].['second'][0]".to_string();
115117
/// assert_eq!(slice_of_data, Value::Array(vec![Value::String(expected_path)]));
116118
/// ```
117-
pub fn find_as_path(&self, json: &Value) -> Value {
118-
Value::Array(
119+
pub fn find_as_path(&self, json: &T) -> T {
120+
T::array(
119121
self.find_slice(json)
120122
.into_iter()
121123
.flat_map(|v| v.to_path())
@@ -554,7 +556,7 @@ mod tests {
554556
#[test]
555557
fn find_slice_test() {
556558
let json: Box<Value> = serde_json::from_str(template_json()).expect("to get json");
557-
let path: Box<JsonPath> = Box::from(
559+
let path: Box<JsonPath<Value>> = Box::from(
558560
JsonPath::try_from("$..book[?(@.author size 10)].title").expect("the path is correct"),
559561
);
560562
let v = path.find_slice(&json);
@@ -565,7 +567,7 @@ mod tests {
565567
#[test]
566568
fn find_in_array_test() {
567569
let json: Box<Value> = Box::new(json!([{"verb": "TEST"}, {"verb": "RUN"}]));
568-
let path: Box<JsonPath> =
570+
let path: Box<JsonPath<Value>> =
569571
Box::from(JsonPath::try_from("$.[?(@.verb == 'TEST')]").expect("the path is correct"));
570572
let v = path.find_slice(&json);
571573
let js = json!({"verb":"TEST"});
@@ -576,7 +578,7 @@ mod tests {
576578
fn length_test() {
577579
let json: Box<Value> =
578580
Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
579-
let path: Box<JsonPath> = Box::from(
581+
let path: Box<JsonPath<Value>> = Box::from(
580582
JsonPath::try_from("$.[?(@.verb == 'TEST')].length()").expect("the path is correct"),
581583
);
582584
let v = path.find(&json);
@@ -585,48 +587,48 @@ mod tests {
585587

586588
let json: Box<Value> =
587589
Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
588-
let path: Box<JsonPath> =
590+
let path: Box<JsonPath<Value>> =
589591
Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
590592
assert_eq!(path.find(&json), json!([3]));
591593

592594
// length of search following the wildcard returns correct result
593595
let json: Box<Value> =
594596
Box::new(json!([{"verb": "TEST"},{"verb": "TEST","x":3}, {"verb": "RUN"}]));
595-
let path: Box<JsonPath> = Box::from(
597+
let path: Box<JsonPath<Value>> = Box::from(
596598
JsonPath::try_from("$.[?(@.verb == 'TEST')].[*].length()")
597599
.expect("the path is correct"),
598600
);
599601
assert_eq!(path.find(&json), json!([3]));
600602

601603
// length of object returns 0
602604
let json: Box<Value> = Box::new(json!({"verb": "TEST"}));
603-
let path: Box<JsonPath> =
605+
let path: Box<JsonPath<Value>> =
604606
Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
605607
assert_eq!(path.find(&json), Value::Null);
606608

607609
// length of integer returns null
608610
let json: Box<Value> = Box::new(json!(1));
609-
let path: Box<JsonPath> =
611+
let path: Box<JsonPath<Value>> =
610612
Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
611613
assert_eq!(path.find(&json), Value::Null);
612614

613615
// length of array returns correct result
614616
let json: Box<Value> = Box::new(json!([[1], [2], [3]]));
615-
let path: Box<JsonPath> =
617+
let path: Box<JsonPath<Value>> =
616618
Box::from(JsonPath::try_from("$.length()").expect("the path is correct"));
617619
assert_eq!(path.find(&json), json!([3]));
618620

619621
// path does not exist returns length null
620622
let json: Box<Value> =
621623
Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
622-
let path: Box<JsonPath> =
624+
let path: Box<JsonPath<Value>> =
623625
Box::from(JsonPath::try_from("$.not.exist.length()").expect("the path is correct"));
624626
assert_eq!(path.find(&json), Value::Null);
625627

626628
// seraching one value returns correct length
627629
let json: Box<Value> =
628630
Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
629-
let path: Box<JsonPath> = Box::from(
631+
let path: Box<JsonPath<Value>> = Box::from(
630632
JsonPath::try_from("$.[?(@.verb == 'RUN')].length()").expect("the path is correct"),
631633
);
632634

@@ -637,7 +639,7 @@ mod tests {
637639
// searching correct path following unexisting key returns length 0
638640
let json: Box<Value> =
639641
Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
640-
let path: Box<JsonPath> = Box::from(
642+
let path: Box<JsonPath<Value>> = Box::from(
641643
JsonPath::try_from("$.[?(@.verb == 'RUN')].key123.length()")
642644
.expect("the path is correct"),
643645
);
@@ -649,7 +651,7 @@ mod tests {
649651
// fetching first object returns length null
650652
let json: Box<Value> =
651653
Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
652-
let path: Box<JsonPath> =
654+
let path: Box<JsonPath<Value>> =
653655
Box::from(JsonPath::try_from("$.[0].length()").expect("the path is correct"));
654656

655657
let v = path.find(&json);
@@ -658,7 +660,7 @@ mod tests {
658660

659661
// length on fetching the index after search gives length of the object (array)
660662
let json: Box<Value> = Box::new(json!([{"prop": [["a", "b", "c"], "d"]}]));
661-
let path: Box<JsonPath> = Box::from(
663+
let path: Box<JsonPath<Value>> = Box::from(
662664
JsonPath::try_from("$.[?(@.prop)].prop.[0].length()").expect("the path is correct"),
663665
);
664666

@@ -668,7 +670,7 @@ mod tests {
668670

669671
// length on fetching the index after search gives length of the object (string)
670672
let json: Box<Value> = Box::new(json!([{"prop": [["a", "b", "c"], "d"]}]));
671-
let path: Box<JsonPath> = Box::from(
673+
let path: Box<JsonPath<Value>> = Box::from(
672674
JsonPath::try_from("$.[?(@.prop)].prop.[1].length()").expect("the path is correct"),
673675
);
674676

@@ -683,7 +685,7 @@ mod tests {
683685
"field":"field",
684686
}));
685687

686-
let path: Box<JsonPath> =
688+
let path: Box<JsonPath<Value>> =
687689
Box::from(JsonPath::try_from("$.field[1]").expect("the path is correct"));
688690
let v = path.find_slice(&json);
689691
assert_eq!(v, vec![NoValue]);
@@ -692,7 +694,7 @@ mod tests {
692694
"field":[0],
693695
}));
694696

695-
let path: Box<JsonPath> =
697+
let path: Box<JsonPath<Value>> =
696698
Box::from(JsonPath::try_from("$.field[1]").expect("the path is correct"));
697699
let v = path.find_slice(&json);
698700
assert_eq!(v, vec![NoValue]);
@@ -704,7 +706,7 @@ mod tests {
704706
"field":"field",
705707
}));
706708

707-
let path: Box<JsonPath> =
709+
let path: Box<JsonPath<Value>> =
708710
Box::from(JsonPath::try_from("$.field[?(@ == 0)]").expect("the path is correct"));
709711
let v = path.find_slice(&json);
710712
assert_eq!(v, vec![NoValue]);
@@ -716,7 +718,7 @@ mod tests {
716718
"field":[{"f":1},{"f":0}],
717719
}));
718720

719-
let path: Box<JsonPath> =
721+
let path: Box<JsonPath<Value>> =
720722
Box::from(JsonPath::try_from("$.field[?(@.f_ == 0)]").expect("the path is correct"));
721723
let v = path.find_slice(&json);
722724
assert_eq!(v, vec![NoValue]);
@@ -728,7 +730,7 @@ mod tests {
728730
"field":[{"f":1},{"f":{"f_":1}}],
729731
}));
730732

731-
let path: Box<JsonPath> =
733+
let path: Box<JsonPath<Value>> =
732734
Box::from(JsonPath::try_from("$..f_").expect("the path is correct"));
733735
let v = path.find_slice(&json);
734736
assert_eq!(
@@ -743,12 +745,12 @@ mod tests {
743745
"field":{"field":[1]},
744746
}));
745747

746-
let path: Box<JsonPath> =
748+
let path: Box<JsonPath<Value>> =
747749
Box::from(JsonPath::try_from("$.field_.field").expect("the path is correct"));
748750
let v = path.find_slice(&json);
749751
assert_eq!(v, vec![NoValue]);
750752

751-
let path: Box<JsonPath> = Box::from(
753+
let path: Box<JsonPath<Value>> = Box::from(
752754
JsonPath::try_from("$.field_.field[?(@ == 1)]").expect("the path is correct"),
753755
);
754756
let v = path.find_slice(&json);
@@ -760,7 +762,7 @@ mod tests {
760762
// searching unexisting value returns length 0
761763
let json: Box<Value> =
762764
Box::new(json!([{"verb": "TEST"},{"verb": "TEST"}, {"verb": "RUN"}]));
763-
let path: Box<JsonPath> = Box::from(
765+
let path: Box<JsonPath<Value>> = Box::from(
764766
JsonPath::try_from("$.[?(@.verb == \"RUN1\")]").expect("the path is correct"),
765767
);
766768
let v = path.find(&json);
@@ -774,15 +776,15 @@ mod tests {
774776
"field":{"field":1},
775777
}));
776778

777-
let path: Box<JsonPath> =
779+
let path: Box<JsonPath<Value>> =
778780
Box::from(JsonPath::try_from("$.field.field.length()").expect("the path is correct"));
779781
let v = path.find_slice(&json);
780782
assert_eq!(v, vec![NoValue]);
781783

782784
let json: Box<Value> = Box::new(json!({
783785
"field":[{"a":1},{"a":1}],
784786
}));
785-
let path: Box<JsonPath> = Box::from(
787+
let path: Box<JsonPath<Value>> = Box::from(
786788
JsonPath::try_from("$.field[?(@.a == 0)].f.length()").expect("the path is correct"),
787789
);
788790
let v = path.find_slice(&json);
@@ -813,14 +815,14 @@ mod tests {
813815
fn logical_exp_test() {
814816
let json: Box<Value> = Box::new(json!({"first":{"second":[{"active":1},{"passive":1}]}}));
815817

816-
let path: Box<JsonPath> = Box::from(
818+
let path: Box<JsonPath<Value>> = Box::from(
817819
JsonPath::try_from("$.first[?(@.does_not_exist && @.does_not_exist >= 1.0)]")
818820
.expect("the path is correct"),
819821
);
820822
let v = path.find_slice(&json);
821823
assert_eq!(v, vec![NoValue]);
822824

823-
let path: Box<JsonPath> = Box::from(
825+
let path: Box<JsonPath<Value>> = Box::from(
824826
JsonPath::try_from("$.first[?(@.does_not_exist >= 1.0)]").expect("the path is correct"),
825827
);
826828
let v = path.find_slice(&json);
@@ -833,7 +835,7 @@ mod tests {
833835
"author":"abcd(Rees)",
834836
}));
835837

836-
let path: Box<JsonPath> = Box::from(
838+
let path: Box<JsonPath<Value>> = Box::from(
837839
JsonPath::try_from("$.[?(@.author ~= '(?i)d\\(Rees\\)')]")
838840
.expect("the path is correct"),
839841
);
@@ -846,7 +848,7 @@ mod tests {
846848
#[test]
847849
fn logical_not_exp_test() {
848850
let json: Box<Value> = Box::new(json!({"first":{"second":{"active":1}}}));
849-
let path: Box<JsonPath> = Box::from(
851+
let path: Box<JsonPath<Value>> = Box::from(
850852
JsonPath::try_from("$.first[?([email protected]_not_exist >= 1.0)]")
851853
.expect("the path is correct"),
852854
);
@@ -859,7 +861,7 @@ mod tests {
859861
)]
860862
);
861863

862-
let path: Box<JsonPath> = Box::from(
864+
let path: Box<JsonPath<Value>> = Box::from(
863865
JsonPath::try_from("$.first[?(!(@.does_not_exist >= 1.0))]")
864866
.expect("the path is correct"),
865867
);
@@ -872,7 +874,7 @@ mod tests {
872874
)]
873875
);
874876

875-
let path: Box<JsonPath> = Box::from(
877+
let path: Box<JsonPath<Value>> = Box::from(
876878
JsonPath::try_from("$.first[?(!(@.second.active == 1) || @.second.active == 1)]")
877879
.expect("the path is correct"),
878880
);
@@ -885,7 +887,7 @@ mod tests {
885887
)]
886888
);
887889

888-
let path: Box<JsonPath> = Box::from(
890+
let path: Box<JsonPath<Value>> = Box::from(
889891
JsonPath::try_from("$.first[?([email protected] == 1 && [email protected] == 1 || [email protected] == 2)]")
890892
.expect("the path is correct"),
891893
);

0 commit comments

Comments
 (0)