json_path/
eval.rs

1mod result_acceptor;
2use result_acceptor::*;
3
4use std::iter::Peekable;
5
6use serde_json::{Map, Value};
7
8use crate::{
9    tokenizer::{
10        ArraySlice, Comparator, Expression, PropertyPathToken, RootPathToken, ScanPathToken, Token,
11    },
12    JsonPathError, JsonPathResult,
13};
14
15pub struct Eval {
16    result_acceptor: Box<dyn ResultAcceptor>,
17}
18
19impl Eval {
20    pub fn new() -> Self {
21        Eval {
22            result_acceptor: Box::new(ScalarResultAcceptor::new()),
23        }
24    }
25    pub fn eval(&mut self, json: &Value, tokens: impl AsRef<Vec<Token>>) -> JsonPathResult<Value> {
26        let mut tokens = tokens.as_ref().iter().peekable();
27
28        match tokens.next() {
29            Some(Token::Root(root)) => self.visit_root(root, json, &mut tokens)?,
30            None => {
31                return Err(JsonPathError::EvaluationError(
32                    "Empty jsonpath provided".to_string(),
33                ))
34            }
35            Some(_) => {
36                return Err(JsonPathError::EvaluationError(
37                    "Invalid start token for the given jsonpath".to_string(),
38                ))
39            }
40        }
41
42        self.result_acceptor.result()
43    }
44
45    fn push_result(&mut self, value: Option<Value>) -> JsonPathResult<()> {
46        self.result_acceptor.accept(value)
47    }
48
49    fn visit_next_token<'a>(
50        &mut self,
51        json: &Value,
52        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
53    ) -> JsonPathResult<()> {
54        match tokens.next() {
55            Some(Token::Root(_root)) => unimplemented!(),
56            Some(Token::Property(property)) => self.visit_property(property, json, tokens),
57            Some(Token::ArrayIndex { indices }) => self.visit_array_index(indices, json, tokens),
58            Some(Token::ArraySlice(array_slice)) => {
59                self.visit_array_slice(array_slice, json, tokens)
60            }
61            Some(Token::Predicate(expression)) => self.visit_predicate(expression, json, tokens),
62            Some(Token::Function(_)) => todo!(),
63            Some(Token::Scan(scan)) => self.visit_scan(scan, json, tokens),
64            Some(Token::Wildcard) => self.visit_wildchard(json, tokens),
65            None => Ok(()),
66        }
67    }
68
69    fn visit_root<'a>(
70        &mut self,
71        _token: &RootPathToken,
72        json: &Value,
73        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
74    ) -> JsonPathResult<()> {
75        match tokens.peek() {
76            None => self.push_result(Some(json.clone())),
77            Some(_) => self.visit_next_token(json, tokens),
78        }
79    }
80
81    fn visit_property<'a>(
82        &mut self,
83        token: &PropertyPathToken,
84        object: &Value,
85        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
86    ) -> JsonPathResult<()> {
87        let object = match object {
88            Value::Object(object) => object,
89            _ => return Ok(()),
90        };
91
92        if token.properties.len() > 1 {
93            match tokens.peek() {
94                None => {
95                    // this is a leaf token, will merge properties into one object
96                    let mut result = Map::new();
97                    for prop in token.properties.iter() {
98                        match object.get(prop) {
99                            Some(v) => result.insert(prop.to_string(), v.clone()),
100                            // TODO: differentiate undefined and null with options
101                            None => result.insert(prop.to_string(), Value::Null),
102                        };
103                    }
104                    self.push_result(Some(Value::Object(result)))
105                }
106                Some(_) => {
107                    // this is a multi property iteration
108                    self.use_array_result_register();
109
110                    for prop in token.properties.iter() {
111                        self.handle_object_property(prop, object, &mut tokens.clone())?;
112                    }
113                    Ok(())
114                }
115            }
116        } else {
117            // single property query
118            let prop = token.properties.first().unwrap();
119            self.handle_object_property(prop, object, tokens)
120        }
121    }
122
123    fn handle_object_property<'a>(
124        &mut self,
125        prop: &String,
126        object: &Map<String, Value>,
127        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
128    ) -> JsonPathResult<()> {
129        match object.get(prop) {
130            Some(v) => match tokens.peek() {
131                None => self.push_result(Some(v.clone())),
132                Some(_) => self.visit_next_token(v, tokens),
133            },
134            None => self.push_result(None),
135        }
136    }
137}
138
139// visit ScanPathToken
140impl Eval {
141    /// upgrade the Eval to return array results
142    fn use_array_result_register(&mut self) {
143        if self.result_acceptor.is_scalar() {
144            self.result_acceptor = Box::new(ArrayResultRegister::new())
145        }
146    }
147
148    fn visit_scan<'a>(
149        &mut self,
150        _token: &ScanPathToken,
151        json: &Value,
152        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
153    ) -> JsonPathResult<()> {
154        if !json.is_array() && !json.is_object() {
155            return Err(JsonPathError::EvaluationError(
156                "Properties scan ('..') can only run on array or object values.".to_string(),
157            ));
158        }
159        self.use_array_result_register();
160        self.walk(json, tokens)
161    }
162
163    fn walk<'a>(
164        &mut self,
165        json: &Value,
166        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
167    ) -> JsonPathResult<()> {
168        self.visit_next_token(json, &mut tokens.clone())?;
169        match json {
170            Value::Object(object) => {
171                for (_k, v) in object {
172                    self.walk(v, &mut tokens.clone())?;
173                }
174            }
175            Value::Array(array) => {
176                for v in array {
177                    self.walk(v, &mut tokens.clone())?;
178                }
179            }
180            _ => {}
181        }
182        Ok(())
183    }
184}
185
186// visit array index/slice token
187impl Eval {
188    fn visit_array_index<'a>(
189        &mut self,
190        indices: &Vec<i32>,
191        json: &Value,
192        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
193    ) -> JsonPathResult<()> {
194        let array = json.as_array().ok_or(JsonPathError::EvaluationError(
195            "Running array index op on non-array object".to_string(),
196        ))?;
197
198        if indices.is_empty() {
199            Err(JsonPathError::EvaluationError(
200                "Invalid array index token, zero index given.".to_string(),
201            ))
202        } else if indices.len() == 1 {
203            let index = *indices.first().unwrap();
204            self.handle_array_index(array, index, tokens)
205        } else {
206            self.use_array_result_register();
207            for index in indices {
208                self.handle_array_index(array, *index, &mut tokens.clone())?;
209            }
210            Ok(())
211        }
212    }
213
214    fn handle_array_index<'a>(
215        &mut self,
216        array: &Vec<Value>,
217        mut index: i32,
218        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
219    ) -> JsonPathResult<()> {
220        if index < 0 {
221            // TODO: revisit the cast here
222            index += array.len() as i32;
223        }
224        if index >= 0 && index < array.len() as i32 {
225            let value = array.get(index as usize).unwrap();
226            match tokens.peek() {
227                None => self.push_result(Some(value.clone())),
228                Some(_t) => self.visit_next_token(value, tokens),
229            }
230        } else {
231            Ok(())
232        }
233    }
234
235    fn visit_array_slice<'a>(
236        &mut self,
237        slice: &ArraySlice,
238        json: &Value,
239        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
240    ) -> JsonPathResult<()> {
241        let array = json.as_array().ok_or(JsonPathError::EvaluationError(
242            "Running array index op on non-array object".to_string(),
243        ))?;
244        self.use_array_result_register();
245        match slice {
246            ArraySlice::From(from) => {
247                let mut start = *from;
248                if start < 0 {
249                    start = (array.len() as i32 + start).max(0);
250                }
251                for index in start..array.len() as i32 {
252                    self.handle_array_index(array, index, &mut tokens.clone())?;
253                }
254                Ok(())
255            }
256            ArraySlice::To(to) => {
257                let mut end = *to;
258                if end < 0 {
259                    end += array.len() as i32;
260                }
261                for index in 0..end {
262                    self.handle_array_index(array, index, &mut tokens.clone())?;
263                }
264                Ok(())
265            }
266            ArraySlice::Between(from, to) => {
267                let mut start = *from;
268                let mut end = *to;
269                if end < 0 {
270                    // scenario for eg. [0:-1]
271                    end += array.len() as i32;
272                }
273                if start < 0 {
274                    // scenario for eg. [0:-1]
275                    start = (array.len() as i32 + start).max(0);
276                }
277                if start < end && !array.is_empty() {
278                    for index in start..end {
279                        self.handle_array_index(array, index, &mut tokens.clone())?;
280                    }
281                }
282                Ok(())
283            }
284        }
285    }
286}
287
288impl Eval {
289    fn visit_wildchard<'a>(
290        &mut self,
291        json: &Value,
292        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
293    ) -> JsonPathResult<()> {
294        self.use_array_result_register();
295        match json {
296            Value::Array(array) => {
297                for index in 0..array.len() {
298                    self.handle_array_index(array, index as i32, &mut tokens.clone())?;
299                }
300            }
301            Value::Object(object) => {
302                for prop in object.keys() {
303                    self.handle_object_property(prop, object, &mut tokens.clone())?;
304                }
305            }
306            _ => {
307                return Err(JsonPathError::EvaluationError(
308                    "Expect array or object for wildcard query.".to_string(),
309                ));
310            }
311        }
312        Ok(())
313    }
314}
315
316impl Eval {
317    fn visit_predicate<'a>(
318        &mut self,
319        expression: &Expression,
320        json: &Value,
321        tokens: &mut Peekable<impl Iterator<Item = &'a Token> + Clone>,
322    ) -> JsonPathResult<()> {
323        let result = self.eval_expr(expression, json)?;
324        let bool = Self::get_bool(result);
325        match (bool, tokens.peek()) {
326            (true, None) => self.push_result(Some(json.clone())),
327            (true, Some(_)) => self.visit_next_token(json, tokens),
328            _ => Ok(()),
329        }
330    }
331
332    fn get_bool(value: Value) -> bool {
333        match value {
334            Value::Bool(b) => b,
335            Value::Null => false,
336            _ => true,
337        }
338    }
339
340    fn eval_expr(&self, expression: &Expression, json: &Value) -> JsonPathResult<Value> {
341        let result = match expression {
342            Expression::JsonQuery(tokens) => {
343                let mut eval = Eval::new();
344                // TODO: support jsonpath query on the root object (using $)
345                eval.eval(json, tokens)?
346            }
347            Expression::Literal(v) => v.clone(),
348            Expression::Not(inner) => {
349                let r = self.eval_expr(inner, json)?;
350                match r {
351                    Value::Bool(b) => Value::Bool(!b),
352                    Value::Null => Value::Bool(true),
353                    _ => Value::Bool(false),
354                }
355            }
356            Expression::Array(v) => {
357                let values = v
358                    .iter()
359                    .map(|e| self.eval_expr(e, json))
360                    .collect::<JsonPathResult<Vec<Value>>>()?;
361                Value::Array(values)
362            }
363            Expression::CompareExpr { op, left, right } => {
364                let left = self.eval_expr(left, json)?;
365                let right = self.eval_expr(right, json)?;
366                let result = match op {
367                    Comparator::Eq => left.eq(&right),
368                    Comparator::Neq => !left.eq(&right),
369                    Comparator::Gt => match (left, right) {
370                        (Value::Number(l), Value::Number(r)) => l.as_f64() > r.as_f64(),
371                        _ => false,
372                    },
373                    Comparator::GtEq => match (left, right) {
374                        (Value::Number(l), Value::Number(r)) => l.as_f64() >= r.as_f64(),
375                        _ => false,
376                    },
377                    Comparator::Lt => match (left, right) {
378                        (Value::Number(l), Value::Number(r)) => l.as_f64() < r.as_f64(),
379                        _ => false,
380                    },
381                    Comparator::LtEq => match (left, right) {
382                        (Value::Number(l), Value::Number(r)) => l.as_f64() <= r.as_f64(),
383                        _ => false,
384                    },
385                    Comparator::RegExpMatch => todo!(), // TODO: implement this
386                    Comparator::AND => Self::get_bool(left) && Self::get_bool(right),
387                    Comparator::OR => Self::get_bool(left) || Self::get_bool(right),
388                    Comparator::IN => match right {
389                        Value::Array(values) => values.contains(&left),
390                        _ => false,
391                    },
392                    Comparator::NIN => match right {
393                        Value::Array(values) => !values.contains(&left),
394                        _ => false,
395                    },
396                    Comparator::SubsetOf => match (left, right) {
397                        (Value::Array(l), Value::Array(r)) => l.iter().all(|c| r.contains(c)),
398                        _ => false,
399                    },
400                    Comparator::AnyOf => match (left, right) {
401                        (Value::Array(l), Value::Array(r)) => l.iter().any(|c| r.contains(c)),
402                        _ => false,
403                    },
404                    Comparator::NoneOf => match (left, right) {
405                        (Value::Array(l), Value::Array(r)) => !l.iter().any(|c| r.contains(c)),
406                        _ => false,
407                    },
408                    Comparator::Contains => match (left, right) {
409                        (Value::Array(values), r) => values.contains(&r),
410                        (Value::String(l), Value::String(r)) => l.contains(&r),
411                        _ => false,
412                    },
413                    Comparator::SizeOf => match (left, right) {
414                        (Value::Array(values), Value::Number(n)) => {
415                            values.len() as i64 == n.as_i64().unwrap_or(-1)
416                        }
417                        (Value::String(s), Value::Number(n)) => {
418                            s.len() as i64 == n.as_i64().unwrap_or(-1)
419                        }
420                        _ => false,
421                    },
422                    Comparator::Empty => match (left, right) {
423                        (Value::Array(values), Value::Bool(b)) => values.is_empty() == b,
424                        (Value::String(s), Value::Bool(b)) => s.is_empty() == b,
425                        (Value::Null, Value::Bool(b)) => b,
426                        _ => false,
427                    },
428                };
429                Value::Bool(result)
430            }
431        };
432        Ok(result)
433    }
434}
435
436#[cfg(test)]
437mod test {
438    use serde_json::{json, Value};
439
440    use crate::{tokenizer::Tokenizer, JsonPathResult};
441
442    use super::Eval;
443
444    pub trait JsonPathQuery {
445        fn query(&self, json_path: &str) -> JsonPathResult<Value>;
446    }
447
448    impl JsonPathQuery for Value {
449        fn query(&self, json_path: &str) -> JsonPathResult<Value> {
450            let tz = Tokenizer::new();
451            let tokens = tz.tokenize(json_path)?;
452            let mut eval = Eval::new();
453            eval.eval(self, tokens)
454        }
455    }
456
457    #[test]
458    fn can_query_root_node() {
459        let json = json!({"data": {"msg": "hello"}});
460        assert_eq!(json.query("$"), Ok(json));
461    }
462
463    #[test]
464    fn can_query_single_property() {
465        assert_eq!(
466            Ok(json!("hello")),
467            json!({"data": {"msg": "hello"}}).query("$.data.msg")
468        );
469    }
470
471    #[test]
472    fn can_query_single_bracket_property() {
473        assert_eq!(
474            Ok(json!("hello")),
475            json!({"data": {"msg": "hello"}}).query("$[\"data\"].msg")
476        )
477    }
478
479    #[test]
480    fn can_query_multiple_bracket_properties() {
481        assert_eq!(
482            Ok(json!(["hello", "jsonpath"])),
483            json!({"data": {"msg": "hello"}, "value": {"msg": "jsonpath"}})
484                .query("$['data','value'].msg")
485        );
486    }
487
488    #[test]
489    fn can_query_and_merge_multiple_bracket_properties() {
490        let json = json!({"data": {"msg1": "hello", "msg2": "jsonpath", "msg3": "xxx"}});
491        assert_eq!(
492            Ok(json!({"msg1": "hello", "msg2": "jsonpath"})),
493            json.query("$.data['msg1','msg2']")
494        )
495    }
496
497    #[test]
498    fn can_scan_properties() {
499        let json = json!({"data": {"item1": {"msg": "hello"}, "item2": {"msg": "jsonpath"}}});
500        assert_eq!(Ok(json!(["hello", "jsonpath"])), json.query("$.data..msg"))
501    }
502
503    #[test]
504    fn can_scan_properties_with_arrays() {
505        let json = json!({"data": {"items": [{"msg": "jsonpath"},  {"msg": "!"}], "msg": "hello"}});
506        assert_eq!(
507            Ok(json!(["hello", "jsonpath", "!"])),
508            json.query("$.data..msg")
509        )
510    }
511
512    #[test]
513    fn support_array_index_with_single_index() {
514        let json = json!({"data": ["item 0", "item 1", "item 2"]});
515        assert_eq!(Ok(json!("item 0")), json.query("$.data[0]"));
516        assert_eq!(Ok(json!("item 1")), json.query("$.data[1]"));
517        assert_eq!(Ok(json!("item 2")), json.query("$.data[2]"));
518        assert_eq!(Ok(Value::Null), json.query("$.data[3]"));
519        assert_eq!(Ok(json!("item 2")), json.query("$.data[-1]"));
520        assert_eq!(Ok(json!("item 1")), json.query("$.data[-2]"));
521        assert_eq!(Ok(json!("item 0")), json.query("$.data[-3]"));
522        assert_eq!(Ok(Value::Null), json.query("$.data[-4]"));
523    }
524
525    #[test]
526    fn support_array_index_with_empty_array() {
527        let json = json!({"data": []});
528        assert_eq!(Ok(Value::Null), json.query("$.data[0]"));
529    }
530
531    #[test]
532    fn support_array_index_with_multiple_indices() {
533        let json = json!({"data": ["item 0", "item 1", "item 2"]});
534        assert_eq!(Ok(json!(["item 0", "item 2"])), json.query("$.data[0,2]"));
535        assert_eq!(Ok(json!(["item 0", "item 2"])), json.query("$.data[0,-1]"));
536        assert_eq!(Ok(json!(["item 1", "item 1"])), json.query("$.data[1,1]"));
537    }
538
539    #[test]
540    fn support_array_slice() {
541        let json = json!({"data": ["item 0", "item 1", "item 2"]});
542        assert_eq!(
543            Ok(json!(["item 0", "item 1", "item 2"])),
544            json.query("$.data[0:3]")
545        );
546        assert_eq!(
547            Ok(json!(["item 0", "item 1", "item 2"])),
548            json.query("$.data[:3]")
549        );
550        assert_eq!(Ok(json!(["item 1", "item 2"])), json.query("$.data[1:]"));
551        assert_eq!(Ok(json!(["item 0", "item 1"])), json.query("$.data[0:-1]"));
552        assert_eq!(Ok(json!(["item 0", "item 1"])), json.query("$.data[:-1]"));
553        assert_eq!(Ok(json!(["item 0", "item 1"])), json.query("$.data[-5:-1]"));
554        assert_eq!(
555            Ok(json!(["item 0", "item 1", "item 2"])),
556            json.query("$.data[-5:]")
557        );
558    }
559
560    #[test]
561    fn support_wildcard_query_on_objects() {
562        let json = json!({"data": {"0": {"msg": "item 0"}, "1": {"msg": "item 1"}}});
563        assert_eq!(Ok(json!(["item 0", "item 1"])), json.query("$.data[*].msg"));
564        let json =
565            json!({"data": {"0": {"msg": {"msg": "item 0"}}, "1": {"msg": {"msg": "item 1"}}}});
566        assert_eq!(
567            Ok(json!(["item 0", "item 1"])),
568            json.query("$.data[*].msg.msg")
569        );
570        assert_eq!(
571            Ok(json!(["item 0", "item 1"])),
572            json.query("$.data.*.msg.msg")
573        );
574    }
575
576    #[test]
577    fn support_wildcard_query_on_arrays() {
578        let json = json!({"data": [{"msg": "item 0"}, {"msg": "item 1"}]});
579        assert_eq!(Ok(json!(["item 0", "item 1"])), json.query("$.data[*].msg"));
580        let json = json!({"data": [ {"msg": {"msg": "item 0"}}, {"msg": {"msg": "item 1"}}]});
581        assert_eq!(
582            Ok(json!(["item 0", "item 1"])),
583            json.query("$.data[*].msg.msg")
584        );
585    }
586
587    #[test]
588    fn support_simple_filters() {
589        let json = json!({"data": [{"msg": "item 0"}, {"msg": "item 1"}]});
590        assert_eq!(
591            Ok(json!(["item 0", "item 1"])),
592            json.query("$.data[*][?(@.msg)].msg")
593        );
594    }
595
596    #[test]
597    fn support_simple_filters_2() {
598        let json = json!({"data": [{"msg": "item 0", "id": 10}, {"msg": "item 1", "id": 11}, {"msg": null, "id": 10}]});
599        assert_eq!(
600            Ok(json!(["item 0"])),
601            json.query("$.data[*][?(@.msg && @.id == 10)].msg")
602        );
603    }
604
605    #[test]
606    fn support_filters_with_in() {
607        let json = json!({"data": [{"msg": "item 0", "id": 10}, {"msg": "item 1", "id": 11}, {"msg": null, "id": 10}]});
608        assert_eq!(
609            Ok(json!(["item 0"])),
610            json.query("$.data[*][?(@.msg in ['item 0'])].msg")
611        );
612        assert_eq!(
613            Ok(json!(["item 0", "item 1", null])),
614            json.query("$.data[*][?(@.id in [10, 11])].msg")
615        );
616    }
617
618    #[test]
619    fn support_filters_with_in2() {
620        let json = json!({"data": [{"msg": "item 0", "id": 10}, {"msg": "item 1", "id": 11}, {"msg": null, "id": 10}]});
621        assert_eq!(
622            Ok(json!(["item 1", null])),
623            json.query("$.data[*][?(@.msg nin ['item 0'])].msg")
624        );
625        assert_eq!(
626            Ok(json!([])),
627            json.query("$.data[*][?(@.id nin [10, 11])].msg")
628        );
629    }
630
631    #[test]
632    fn support_filters_with_subsetof() {
633        let json = json!({"data": [{"sizes": ["M", "L"], "id": 10}, {"sizes": ["M",  "XXL"], "id": 11}, {"sizes": ["M"], "id": 12}]});
634        assert_eq!(
635            Ok(json!([10, 12])),
636            json.query("$.data[*][?(@.sizes subsetof ['M', \"L\"])].id")
637        );
638    }
639
640    #[test]
641    fn support_filters_with_anyof() {
642        let json = json!({"data": [{"sizes": ["M", "L"], "id": 10}, {"sizes": ["M",  "XXL"], "id": 11}, {"sizes": ["XXL"], "id": 12}]});
643        assert_eq!(
644            Ok(json!([10, 11])),
645            json.query("$.data[*][?(@.sizes anyof ['M', \"L\"])].id")
646        );
647    }
648
649    #[test]
650    fn support_filters_with_noneof() {
651        let json = json!({"data": [{"sizes": ["M", "L"], "id": 10}, {"sizes": ["M",  "XXL"], "id": 11}, {"sizes": ["XXL"], "id": 12}]});
652        assert_eq!(
653            Ok(json!([12])),
654            json.query("$.data[*][?(@.sizes noneof ['M', \"L\"])].id")
655        );
656    }
657
658    #[test]
659    fn support_filters_with_contains() {
660        let json = json!({"data": [{"sizes": ["M", "L"], "id": 10}, {"sizes": ["M",  "XXL"], "id": 11}, {"sizes": ["XXL"], "id": 12}]});
661        assert_eq!(
662            Ok(json!([10, 11])),
663            json.query("$.data[*][?(@.sizes contains 'M')].id")
664        );
665
666        let json = json!({"data": [{"msg": "item 0", "id": 10}, {"msg": "item 1", "id": 11}, {"msg": null, "id": 10}]});
667        assert_eq!(
668            Ok(json!(["item 0"])),
669            json.query("$.data[*][?(@.msg contains '0')].msg")
670        );
671    }
672
673    #[test]
674    fn support_filters_with_sizeof() {
675        let json = json!({"data": [{"sizes": ["M", "L"], "id": 10}, {"sizes": ["M",  "XXL"], "id": 11}, {"sizes": ["XXL"], "id": 12}]});
676        assert_eq!(
677            Ok(json!([10, 11])),
678            json.query("$.data[*][?(@.sizes size 2)].id")
679        );
680
681        let json = json!({"data": [{"msg": "item 0", "id": 10}, {"msg": "item 1", "id": 11}, {"msg": null, "id": 10}]});
682        assert_eq!(
683            Ok(json!(["item 0", "item 1"])),
684            json.query("$.data[*][?(@.msg size 6)].msg")
685        );
686    }
687
688    #[test]
689    fn support_filters_with_empty_op() {
690        let json = json!({"data": [{"sizes": ["M", "L"], "id": 10}, {"sizes": ["M",  "XXL"], "id": 11}, {"sizes": [], "id": 12}]});
691        assert_eq!(
692            Ok(json!([10, 11])),
693            json.query("$.data[*][?(@.sizes empty false)].id")
694        );
695
696        let json = json!({"data": [{"msg": "item 0", "id": 10}, {"msg": "item 1", "id": 11}, {"msg": null, "id": 12}]});
697        assert_eq!(
698            Ok(json!([12])),
699            json.query("$.data[*][?(@.msg empty true)].id")
700        );
701    }
702
703    #[test]
704    fn support_filters_with_not_op() {
705        let json = json!({"data": [{"sizes": ["M", "L"], "id": 10}, {"sizes": ["M",  "XXL"], "id": 11}, {"sizes": [], "id": 12}]});
706        assert_eq!(
707            Ok(json!([12])),
708            json.query("$.data[*][?(!(@.sizes empty false))].id")
709        );
710
711        let json = json!({"data": [{"msg": "item 0", "id": 10}, {"msg": "item 1", "id": 11}, {"msg": null, "id": 12}]});
712        assert_eq!(Ok(json!([12])), json.query("$.data[*][?(!@.msg)].id"));
713    }
714
715    #[test]
716    fn support_scan_and_filter() {
717        let json = json!([1, 2, 3]);
718        assert_eq!(Ok(json!([1, 2, 3])), json.query("$..[?(@>=1)]"));
719    }
720}