Implement JSONPath multiple selectors

This commit is contained in:
Fabrice Reix 2025-09-15 13:11:17 +02:00
parent 9de2099f65
commit f91ed7c2cd
No known key found for this signature in database
GPG Key ID: 71B8BAD935E3190A
4 changed files with 34 additions and 7 deletions

View File

@ -20,7 +20,7 @@ mod error;
mod primitives;
mod query;
mod segments;
mod selector;
mod selectors;
pub use error::{ParseError, ParseErrorKind};
use hurl_core::reader::Reader;

View File

@ -18,7 +18,7 @@
use super::{primitives::literal, primitives::try_literal, ParseResult};
use crate::jsonpath2::{
parser::{selector, ParseError, ParseErrorKind},
parser::{selectors, ParseError, ParseErrorKind},
ChildSegment, DescendantSegment, NameSelector, Segment, Selector, WildcardSelector,
};
use hurl_core::reader::Reader;
@ -43,9 +43,7 @@ fn try_segment(reader: &mut Reader) -> ParseResult<Option<Segment>> {
} else {
return Ok(None);
};
let first_selector = selector::parse(reader)?;
let selectors = vec![first_selector];
// TODO: select more than one selector
let selectors = selectors::parse(reader)?;
literal("]", reader)?;
let segment = if is_descendant_segment {
Segment::Descendant(DescendantSegment::new(selectors))

View File

@ -27,7 +27,19 @@ use hurl_core::reader::Reader;
use super::ParseResult;
pub fn parse(reader: &mut Reader) -> ParseResult<Selector> {
pub fn parse(reader: &mut Reader) -> ParseResult<Vec<Selector>> {
let mut selectors = vec![];
loop {
let selector = selector(reader)?;
selectors.push(selector);
if !try_literal(",", reader) {
break;
}
}
Ok(selectors)
}
pub fn selector(reader: &mut Reader) -> ParseResult<Selector> {
let initial_state = reader.cursor();
if let Some(name_selector) = try_name_selector(reader)? {
return Ok(Selector::Name(name_selector));
@ -118,9 +130,22 @@ mod tests {
#[test]
pub fn test_parse() {
let mut reader = Reader::new("'store'");
let mut reader = Reader::new("'store',0");
assert_eq!(
parse(&mut reader).unwrap(),
vec![
Selector::Name(NameSelector::new("store".to_string())),
Selector::Index(IndexSelector::new(0))
]
);
assert_eq!(reader.cursor().index, CharPos(9));
}
#[test]
pub fn test_selector() {
let mut reader = Reader::new("'store'");
assert_eq!(
selector(&mut reader).unwrap(),
Selector::Name(NameSelector::new("store".to_string()))
);
assert_eq!(reader.cursor().index, CharPos(7));

View File

@ -171,6 +171,10 @@ fn child_segment() {
eval(&store_value(), "$.book[?@.isbn]"),
vec![book2_value(), book3_value()]
);
assert_eq!(
eval(&store_value(), "$.book[0,1]"),
vec![book0_value(), book1_value()]
);
}
#[test]