jsonpath_rust/query/
filter.rs1use crate::parser::model::Filter;
2use crate::query::queryable::Queryable;
3use crate::query::state::{Data, Pointer, State};
4use crate::query::Query;
5
6impl Query for Filter {
7 fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
8 let root = state.root;
9 state.flat_map(|p| {
10 if p.is_internal() {
11 Data::Value(self.filter_item(p, root).into())
12 } else if let Some(items) = p.inner.as_array() {
13 Data::Refs(
14 items
15 .into_iter()
16 .enumerate()
17 .filter(|(_, item)| self.filter_item(Pointer::empty(*item), root))
18 .map(|(idx, item)| Pointer::idx(item, p.path.clone(), idx))
19 .collect(),
20 )
21 } else if let Some(items) = p.inner.as_object() {
22 Data::Refs(
23 items
24 .into_iter()
25 .filter(|(_, item)| self.filter_item(Pointer::empty(*item), root))
26 .map(|(key, item)| Pointer::key(item, p.path.clone(), key))
27 .collect(),
28 )
29 } else {
30 return Data::Nothing;
31 }
32 })
33 }
34}
35
36impl Filter {
37 fn process_elem<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
38 let process_cond = |filter: &Filter| {
39 filter
40 .process(state.clone())
41 .ok_val()
42 .and_then(|v| v.as_bool())
43 .unwrap_or_default()
44 };
45 match self {
46 Filter::Or(ors) => State::bool(ors.iter().any(process_cond), state.root),
47 Filter::And(ands) => State::bool(ands.iter().all(process_cond), state.root),
48 Filter::Atom(atom) => atom.process(state),
49 }
50 }
51
52 fn filter_item<'a, T: Queryable>(&self, item: Pointer<'a, T>, root: &T) -> bool {
53 self.process_elem(State::data(root, Data::Ref(item.clone())))
54 .ok_val()
55 .and_then(|v| v.as_bool())
56 .unwrap_or_default()
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::query::js_path;
63 use serde_json::json;
64
65 #[test]
66 fn smoke_ok() {
67 let json = json!({"a" : [1,2,3]});
68
69 assert_eq!(
70 js_path("$.a[? @ > 1]", &json),
71 Ok(vec![
72 (&json!(2), "$['a'][1]".to_string()).into(),
73 (&json!(3), "$['a'][2]".to_string()).into(),
74 ])
75 );
76 }
77
78 #[test]
79 fn existence() {
80 let json = json!({
81 "a": {
82 "a":{"b":1},
83 "c": {
84 "b": 2
85 },
86 "d": {
87 "b1": 3
88 }
89 }
90 });
91 assert_eq!(
92 js_path("$.a[?@.b]", &json),
93 Ok(vec![
94 (&json!({"b":1}), "$['a']['a']".to_string()).into(),
95 (&json!({"b":2}), "$['a']['c']".to_string()).into(),
96 ])
97 );
98 }
99
100 #[test]
101 fn existence_or() {
102 let json = json!({
103 "a": {
104 "a":{"b":1},
105 "c": {
106 "b": 2
107 },
108 "d": {
109 "b1": 3
110 },
111 "e": {
112 "b2": 3
113 }
114 }
115 });
116 assert_eq!(
117 js_path("$.a[?@.b || @.b1]", &json),
118 Ok(vec![
119 (&json!({"b":1}), "$['a']['a']".to_string()).into(),
120 (&json!({"b":2}), "$['a']['c']".to_string()).into(),
121 (&json!({"b1":3}), "$['a']['d']".to_string()).into(),
122 ])
123 );
124 }
125}