jsonpath_lib/selector/
selector_impl.rs

1use std::collections::HashSet;
2use std::rc::Rc;
3
4use serde_json::map::Entry;
5use serde_json::{Number, Value};
6
7use super::terms::*;
8use super::utils;
9use crate::paths::{tokens::*, ParserTokenHandler, PathParser, StrRange};
10use crate::JsonPathError;
11use crate::{debug, trace};
12
13#[derive(Debug, Default)]
14pub struct JsonSelector<'a> {
15    parser: Option<Rc<PathParser<'a>>>,
16    value: Option<&'a Value>,
17    tokens: Vec<ParseToken>,
18    current: Option<Vec<&'a Value>>,
19    selectors: Vec<JsonSelector<'a>>,
20    selector_filter: FilterTerms<'a>,
21}
22
23impl<'a> JsonSelector<'a> {
24    pub fn new(parser: PathParser<'a>) -> Self {
25        JsonSelector {
26            parser: Some(Rc::new(parser)),
27            value: None,
28            tokens: Vec::new(),
29            current: None,
30            selectors: Vec::new(),
31            selector_filter: FilterTerms(Vec::new()),
32        }
33    }
34
35    pub fn new_ref(parser: Rc<PathParser<'a>>) -> Self {
36        JsonSelector {
37            parser: Some(parser),
38            value: None,
39            tokens: Vec::new(),
40            current: None,
41            selectors: Vec::new(),
42            selector_filter: FilterTerms(Vec::new()),
43        }
44    }
45
46    pub fn reset_parser(&mut self, parser: PathParser<'a>) -> &mut Self {
47        self.parser = Some(Rc::new(parser));
48        self
49    }
50
51    pub fn reset_parser_ref(&mut self, parser: Rc<PathParser<'a>>) -> &mut Self {
52        self.parser = Some(parser);
53        self
54    }
55
56    pub fn reset_value(&mut self) -> &mut Self {
57        self.current = None;
58        self
59    }
60
61    pub fn value(&mut self, v: &'a Value) -> &mut Self {
62        self.value = Some(v);
63        self
64    }
65
66    fn _select(&mut self) -> Result<(), JsonPathError> {
67        let parser = self.parser.take();
68        if let Some(parser) = parser.as_ref() {
69            let _ = parser.parse(self);
70        }
71        self.parser = parser;
72
73        Ok(())
74    }
75
76    pub fn select_as<T: serde::de::DeserializeOwned>(&mut self) -> Result<Vec<T>, JsonPathError> {
77        self._select()?;
78
79        match &self.current {
80            Some(vec) => {
81                let mut ret = Vec::new();
82                for v in vec {
83                    match T::deserialize(*v) {
84                        Ok(v) => ret.push(v),
85                        Err(e) => return Err(JsonPathError::Serde(e.to_string())),
86                    }
87                }
88                Ok(ret)
89            }
90            _ => Err(JsonPathError::EmptyValue),
91        }
92    }
93
94    pub fn select_as_str(&mut self) -> Result<String, JsonPathError> {
95        self._select()?;
96
97        match &self.current {
98            Some(r) => {
99                Ok(serde_json::to_string(r).map_err(|e| JsonPathError::Serde(e.to_string()))?)
100            }
101            _ => Err(JsonPathError::EmptyValue),
102        }
103    }
104
105    pub fn select(&mut self) -> Result<Vec<&'a Value>, JsonPathError> {
106        self._select()?;
107
108        match &self.current {
109            Some(r) => Ok(r.to_vec()),
110            _ => Err(JsonPathError::EmptyValue),
111        }
112    }
113
114    fn compute_absolute_path_filter<F>(
115        &mut self,
116        token: &ParseToken,
117        parse_value_reader: &F,
118    ) -> bool
119    where
120        F: Fn(&StrRange) -> &'a str,
121    {
122        if !self.selectors.is_empty() {
123            match token {
124                ParseToken::Absolute | ParseToken::Relative | ParseToken::Filter(_) => {
125                    let selector = self.selectors.pop().unwrap();
126
127                    if let Some(current) = &selector.current {
128                        let term = current.into();
129
130                        if let Some(s) = self.selectors.last_mut() {
131                            s.selector_filter.push_term(Some(term));
132                        } else {
133                            self.selector_filter.push_term(Some(term));
134                        }
135                    } else {
136                        unreachable!()
137                    }
138                }
139                _ => {}
140            }
141        }
142
143        if self.selectors.is_empty() {
144            return false;
145        }
146
147        self.selectors
148            .last_mut()
149            .unwrap()
150            .handle(token, parse_value_reader);
151        true
152    }
153}
154
155impl<'a> JsonSelector<'a> {
156    fn visit_absolute(&mut self) {
157        if self.current.is_some() {
158            if let Some(value) = self.value {
159                let selector = JsonSelector {
160                    parser: None,
161                    value: Some(value),
162                    tokens: Vec::new(),
163                    current: Some(vec![value]),
164                    selectors: Vec::new(),
165                    selector_filter: FilterTerms(Vec::new()),
166                };
167                self.selectors.push(selector);
168            }
169            return;
170        }
171
172        if let Some(v) = &self.value {
173            self.current = Some(vec![v]);
174        }
175    }
176
177    fn visit_relative(&mut self) {
178        if let Some(ParseToken::Array) = self.tokens.last() {
179            let array_token = self.tokens.pop();
180            if let Some(ParseToken::Leaves) = self.tokens.last() {
181                self.tokens.pop();
182                self.current = self.selector_filter.collect_all(self.current.take());
183            }
184            self.tokens.push(array_token.unwrap());
185        }
186        self.selector_filter.new_filter_context();
187    }
188
189    fn visit_array_eof(&mut self) {
190        if self.is_last_before_token_match(ParseToken::Array) {
191            if let Some(Some(e)) = self.selector_filter.pop_term() {
192                if let ExprTerm::String(key) = e {
193                    self.current = self
194                        .selector_filter
195                        .filter_next_with_str(self.current.take(), key);
196                    self.tokens.pop();
197                    return;
198                }
199
200                self.selector_filter.push_term(Some(e));
201            }
202        }
203
204        if self.is_last_before_token_match(ParseToken::Leaves) {
205            self.tokens.pop();
206            self.tokens.pop();
207            if let Some(Some(e)) = self.selector_filter.pop_term() {
208                let selector_filter_consumed = match e {
209                    ExprTerm::Number(n) => {
210                        self.current = self
211                            .selector_filter
212                            .collect_all_with_num(self.current.take(), utils::to_f64(&n));
213                        self.selector_filter.pop_term();
214                        true
215                    }
216                    ExprTerm::String(key) => {
217                        self.current = self
218                            .selector_filter
219                            .collect_all_with_str(self.current.take(), key);
220                        self.selector_filter.pop_term();
221                        true
222                    }
223                    _ => {
224                        self.selector_filter.push_term(Some(e));
225                        false
226                    }
227                };
228
229                if selector_filter_consumed {
230                    return;
231                }
232            }
233        }
234
235        if let Some(Some(e)) = self.selector_filter.pop_term() {
236            match e {
237                ExprTerm::Number(n) => {
238                    self.current = self
239                        .selector_filter
240                        .collect_next_with_num(self.current.take(), utils::to_f64(&n));
241                }
242                ExprTerm::String(key) => {
243                    self.current = self
244                        .selector_filter
245                        .collect_next_with_str(self.current.take(), &[key]);
246                }
247                ExprTerm::Json(rel, _, v) => {
248                    if v.is_empty() {
249                        self.current = Some(Vec::new());
250                    } else if let Some(vec) = rel {
251                        self.current = Some(vec);
252                    } else {
253                        self.current = Some(v);
254                    }
255                }
256                ExprTerm::Bool(false) => {
257                    self.current = Some(vec![]);
258                }
259                _ => {}
260            }
261        }
262
263        self.tokens.pop();
264    }
265
266    fn is_last_before_token_match(&mut self, token: ParseToken) -> bool {
267        if self.tokens.len() > 1 {
268            return token == self.tokens[self.tokens.len() - 2];
269        }
270
271        false
272    }
273
274    fn visit_all(&mut self) {
275        if let Some(ParseToken::Array) = self.tokens.last() {
276            self.tokens.pop();
277        }
278
279        match self.tokens.last() {
280            Some(ParseToken::Leaves) => {
281                self.tokens.pop();
282                self.current = self.selector_filter.collect_all(self.current.take());
283            }
284            Some(ParseToken::In) => {
285                self.tokens.pop();
286                self.current = self.selector_filter.collect_next_all(self.current.take());
287            }
288            _ => {
289                self.current = self.selector_filter.collect_next_all(self.current.take());
290            }
291        }
292    }
293
294    fn visit_key(&mut self, key: &'a str) {
295        if let Some(ParseToken::Array) = self.tokens.last() {
296            self.selector_filter.push_term(Some(ExprTerm::String(key)));
297            return;
298        }
299
300        if let Some(t) = self.tokens.pop() {
301            if self.selector_filter.is_term_empty() {
302                match t {
303                    ParseToken::Leaves => {
304                        self.current = self
305                            .selector_filter
306                            .collect_all_with_str(self.current.take(), key)
307                    }
308                    ParseToken::In => {
309                        self.current = self
310                            .selector_filter
311                            .collect_next_with_str(self.current.take(), &[key])
312                    }
313                    _ => {}
314                }
315            } else {
316                match t {
317                    ParseToken::Leaves => {
318                        self.current = self
319                            .selector_filter
320                            .filter_all_with_str(self.current.take(), key);
321                    }
322                    ParseToken::In => {
323                        self.current = self
324                            .selector_filter
325                            .filter_next_with_str(self.current.take(), key);
326                    }
327                    _ => {}
328                }
329            }
330        }
331    }
332
333    fn visit_keys(&mut self, keys: &[&'a str]) {
334        if !self.selector_filter.is_term_empty() {
335            unimplemented!("keys in filter");
336        }
337
338        if let Some(ParseToken::Array) = self.tokens.pop() {
339            self.current = self
340                .selector_filter
341                .collect_next_with_str(self.current.take(), keys);
342        } else {
343            unreachable!();
344        }
345    }
346
347    fn visit_filter(&mut self, ft: &FilterToken) {
348        let right = match self.selector_filter.pop_term() {
349            Some(Some(right)) => right,
350            Some(None) => ExprTerm::Json(
351                None,
352                None,
353                match &self.current {
354                    Some(current) => current.to_vec(),
355                    _ => unreachable!(),
356                },
357            ),
358            _ => ExprTerm::Json(None, None, vec![]), //panic!("empty term right"),
359        };
360
361        let mut left = match self.selector_filter.pop_term() {
362            Some(Some(left)) => left,
363            Some(None) => ExprTerm::Json(
364                None,
365                None,
366                match &self.current {
367                    Some(current) => current.to_vec(),
368                    _ => unreachable!(),
369                },
370            ),
371            _ => ExprTerm::Json(None, None, vec![]), //panic!("empty term left"),
372        };
373
374        let expr = match ft {
375            FilterToken::Equal => left.eq_(right),
376            FilterToken::NotEqual => left.ne_(right),
377            FilterToken::Greater => left.gt(right),
378            FilterToken::GreaterOrEqual => left.ge(right),
379            FilterToken::Little => left.lt(right),
380            FilterToken::LittleOrEqual => left.le(right),
381            FilterToken::And => left.and(right),
382            FilterToken::Or => left.or(right),
383        };
384
385        self.selector_filter.push_term(Some(expr));
386    }
387
388    fn visit_range(&mut self, from: &Option<isize>, to: &Option<isize>, step: &Option<usize>) {
389        if !self.selector_filter.is_term_empty() {
390            unimplemented!("range syntax in filter");
391        }
392
393        if let Some(ParseToken::Array) = self.tokens.pop() {
394            let mut tmp = Vec::new();
395            if let Some(current) = &self.current {
396                for v in current {
397                    if let Value::Array(vec) = v {
398                        let from = if let Some(from) = from {
399                            utils::abs_index(*from, vec.len())
400                        } else {
401                            0
402                        };
403
404                        let to = if let Some(to) = to {
405                            utils::abs_index(*to, vec.len())
406                        } else {
407                            vec.len()
408                        };
409
410                        for i in (from..to).step_by(match step {
411                            Some(step) => *step,
412                            _ => 1,
413                        }) {
414                            if let Some(v) = vec.get(i) {
415                                tmp.push(v);
416                            }
417                        }
418                    }
419                }
420            }
421            self.current = Some(tmp);
422        } else {
423            unreachable!();
424        }
425    }
426
427    fn visit_union(&mut self, indices: &[isize]) {
428        if !self.selector_filter.is_term_empty() {
429            unimplemented!("union syntax in filter");
430        }
431
432        if let Some(ParseToken::Array) = self.tokens.pop() {
433            let mut tmp = Vec::new();
434            if let Some(current) = &self.current {
435                for v in current {
436                    if let Value::Array(vec) = v {
437                        for i in indices {
438                            if let Some(v) = vec.get(utils::abs_index(*i, vec.len())) {
439                                tmp.push(v);
440                            }
441                        }
442                    }
443                }
444            }
445
446            self.current = Some(tmp);
447        } else {
448            unreachable!();
449        }
450    }
451}
452
453impl<'a> ParserTokenHandler<'a> for JsonSelector<'a> {
454    fn handle<F>(&mut self, token: &ParseToken, parse_value_reader: &F)
455    where
456        F: Fn(&StrRange) -> &'a str,
457    {
458        debug!("token: {:?}, stack: {:?}", token, self.tokens);
459
460        if self.compute_absolute_path_filter(token, parse_value_reader) {
461            return;
462        }
463
464        match token {
465            ParseToken::Absolute => self.visit_absolute(),
466            ParseToken::Relative => self.visit_relative(),
467            ParseToken::In | ParseToken::Leaves | ParseToken::Array => {
468                self.tokens.push(token.clone());
469            }
470            ParseToken::ArrayEof => self.visit_array_eof(),
471            ParseToken::All => self.visit_all(),
472            ParseToken::Bool(b) => {
473                self.selector_filter.push_term(Some(ExprTerm::Bool(*b)));
474            }
475            ParseToken::Key(s) => {
476                let key = parse_value_reader(s);
477                self.visit_key(key);
478            }
479            ParseToken::Keys(keys) => {
480                let keys: Vec<&str> = keys.iter().map(parse_value_reader).collect();
481                self.visit_keys(&keys)
482            }
483            ParseToken::Number(v) => {
484                self.selector_filter
485                    .push_term(Some(ExprTerm::Number(Number::from_f64(*v).unwrap())));
486            }
487            ParseToken::Filter(ref ft) => self.visit_filter(ft),
488            ParseToken::Range(from, to, step) => self.visit_range(from, to, step),
489            ParseToken::Union(indices) => self.visit_union(indices),
490            ParseToken::Eof => {
491                debug!("visit_token eof");
492            }
493        }
494    }
495}
496
497#[derive(Default)]
498pub struct JsonSelectorMut<'a> {
499    value: Option<Value>,
500    parser: Option<Rc<PathParser<'a>>>,
501}
502
503impl<'a> JsonSelectorMut<'a> {
504    pub fn new(parser: PathParser<'a>) -> Self {
505        Self::new_ref(Rc::new(parser))
506    }
507
508    pub fn new_ref(parser: Rc<PathParser<'a>>) -> Self {
509        JsonSelectorMut {
510            value: None,
511            parser: Some(parser),
512        }
513    }
514
515    pub fn reset_parser(&mut self, parser: PathParser<'a>) -> &mut Self {
516        self.parser = Some(Rc::new(parser));
517        self
518    }
519
520    pub fn reset_parser_ref(&mut self, parser: Rc<PathParser<'a>>) -> &mut Self {
521        self.parser = Some(parser);
522        self
523    }
524
525    pub fn value(&mut self, value: Value) -> &mut Self {
526        self.value = Some(value);
527        self
528    }
529
530    pub fn take(&mut self) -> Option<Value> {
531        self.value.take()
532    }
533
534    pub fn delete(&mut self) -> Result<&mut Self, JsonPathError> {
535        self.replace_with(&mut |_| Some(Value::Null))
536    }
537
538    pub fn remove(&mut self) -> Result<&mut Self, JsonPathError> {
539        self.replace_with(&mut |_| None)
540    }
541
542    fn select(&self) -> Result<Vec<&Value>, JsonPathError> {
543        let mut selector = JsonSelector::default();
544
545        if let Some(parser) = self.parser.as_ref() {
546            selector.reset_parser_ref(Rc::clone(parser));
547        } else {
548            return Err(JsonPathError::EmptyPath);
549        }
550
551        if let Some(value) = self.value.as_ref() {
552            selector.value(value);
553        } else {
554            return Err(JsonPathError::EmptyValue);
555        }
556
557        selector.select()
558    }
559
560    pub fn replace_with<F>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError>
561    where
562        F: FnMut(Value) -> Option<Value>,
563    {
564        let result = self.select()?;
565        let paths = self.compute_paths(result);
566
567        if let Some(ref mut value) = &mut self.value {
568            for tokens in paths {
569                Self::replace_value(tokens, value, fun);
570            }
571        }
572
573        Ok(self)
574    }
575
576    fn replace_value<F>(mut tokens: Vec<String>, value: &mut Value, fun: &mut F)
577    where
578        F: FnMut(Value) -> Option<Value>,
579    {
580        let mut target = value;
581
582        let last_index = tokens.len().saturating_sub(1);
583        for (i, token) in tokens.drain(..).enumerate() {
584            let target_once = target;
585            let is_last = i == last_index;
586            let target_opt = match *target_once {
587                Value::Object(ref mut map) => {
588                    if is_last {
589                        if let Entry::Occupied(mut e) = map.entry(token) {
590                            let v = e.insert(Value::Null);
591                            if let Some(res) = fun(v) {
592                                e.insert(res);
593                            } else {
594                                e.remove();
595                            }
596                        }
597                        return;
598                    }
599                    map.get_mut(&token)
600                }
601                Value::Array(ref mut vec) => {
602                    if let Ok(x) = token.parse::<usize>() {
603                        if is_last {
604                            if x < vec.len() {
605                                let v = std::mem::replace(&mut vec[x], Value::Null);
606                                if let Some(res) = fun(v) {
607                                    vec[x] = res;
608                                } else {
609                                    vec.remove(x);
610                                }
611                            }
612                            return;
613                        }
614                        vec.get_mut(x)
615                    } else {
616                        None
617                    }
618                }
619                _ => None,
620            };
621
622            if let Some(t) = target_opt {
623                target = t;
624            } else {
625                break;
626            }
627        }
628    }
629
630    fn compute_paths(&self, mut result: Vec<&Value>) -> Vec<Vec<String>> {
631        let mut visited = HashSet::new();
632        let mut visited_order = Vec::new();
633
634        if let Some(origin) = &self.value {
635            let mut tokens = Vec::new();
636            Self::walk(
637                origin,
638                &mut result,
639                &mut tokens,
640                &mut visited,
641                &mut visited_order,
642            );
643        }
644
645        visited_order
646    }
647
648    fn walk(
649        origin: &Value,
650        target: &mut Vec<&Value>,
651        tokens: &mut Vec<String>,
652        visited: &mut HashSet<*const Value>,
653        visited_order: &mut Vec<Vec<String>>,
654    ) -> bool {
655        trace!("{:?}, {:?}", target, tokens);
656
657        if target.is_empty() {
658            return true;
659        }
660
661        target.retain(|t| {
662            if std::ptr::eq(origin, *t) {
663                if visited.insert(*t) {
664                    visited_order.push(tokens.to_vec());
665                }
666                false
667            } else {
668                true
669            }
670        });
671
672        match origin {
673            Value::Array(vec) => {
674                for (i, v) in vec.iter().enumerate() {
675                    tokens.push(i.to_string());
676                    if Self::walk(v, target, tokens, visited, visited_order) {
677                        return true;
678                    }
679                    tokens.pop();
680                }
681            }
682            Value::Object(map) => {
683                for (k, v) in map {
684                    tokens.push(k.clone());
685                    if Self::walk(v, target, tokens, visited, visited_order) {
686                        return true;
687                    }
688                    tokens.pop();
689                }
690            }
691            _ => {}
692        }
693
694        false
695    }
696}