Split jsonpath index selector (unique/multiple index)

- specify one index to return one element
- specify two or more index to return a collection of elements
This commit is contained in:
Fabrice Reix 2023-05-05 17:40:31 +02:00 committed by jcamiel
parent a97b172e58
commit 479e9e97cd
No known key found for this signature in database
GPG Key ID: 07FF11CFD55356CC
3 changed files with 33 additions and 34 deletions

View File

@ -28,7 +28,8 @@ pub struct Query {
pub enum Selector { pub enum Selector {
Wildcard, Wildcard,
NameChild(String), NameChild(String),
ArrayIndex(Vec<usize>), // one or more indexes (separated by comma) ArrayIndex(usize), // one unique index
ArrayIndices(Vec<usize>), // two or more indexes (separated by comma)
ArraySlice(Slice), ArraySlice(Slice),
ArrayWildcard, ArrayWildcard,
Filter(Predicate), Filter(Predicate),

View File

@ -61,6 +61,9 @@ impl Selector {
Selector::NameChild(field) => root Selector::NameChild(field) => root
.get(field) .get(field)
.map(|result| JsonpathResult::SingleEntry(result.clone())), .map(|result| JsonpathResult::SingleEntry(result.clone())),
Selector::ArrayIndex(index) => root
.get(index)
.map(|result| JsonpathResult::SingleEntry(result.clone())),
// Selectors returning a collection ("indefinite") // Selectors returning a collection ("indefinite")
Selector::Wildcard | Selector::ArrayWildcard => { Selector::Wildcard | Selector::ArrayWildcard => {
@ -163,14 +166,7 @@ impl Selector {
}; };
Some(JsonpathResult::Collection(elements)) Some(JsonpathResult::Collection(elements))
} }
Selector::ArrayIndices(indexes) => {
// Selectors returning one or the other
Selector::ArrayIndex(indexes) => {
if indexes.len() == 1 {
let index = indexes[0];
root.get(index)
.map(|result| JsonpathResult::SingleEntry(result.clone()))
} else {
let mut values = vec![]; let mut values = vec![];
for index in indexes { for index in indexes {
if let Some(value) = root.get(index) { if let Some(value) = root.get(index) {
@ -182,7 +178,6 @@ impl Selector {
} }
} }
} }
}
impl Predicate { impl Predicate {
pub fn eval(&self, elem: serde_json::Value) -> bool { pub fn eval(&self, elem: serde_json::Value) -> bool {
@ -322,7 +317,7 @@ mod tests {
selectors: vec![ selectors: vec![
Selector::NameChild("store".to_string()), Selector::NameChild("store".to_string()),
Selector::NameChild("book".to_string()), Selector::NameChild("book".to_string()),
Selector::ArrayIndex(vec![0]), Selector::ArrayIndex(0),
Selector::NameChild("title".to_string()), Selector::NameChild("title".to_string()),
], ],
}; };
@ -401,11 +396,11 @@ mod tests {
#[test] #[test]
pub fn test_selector_array_index() { pub fn test_selector_array_index() {
assert_eq!( assert_eq!(
Selector::ArrayIndex(vec![0]).eval(&json_books()).unwrap(), Selector::ArrayIndex(0).eval(&json_books()).unwrap(),
JsonpathResult::SingleEntry(json_first_book()) JsonpathResult::SingleEntry(json_first_book())
); );
assert_eq!( assert_eq!(
Selector::ArrayIndex(vec![1, 2]) Selector::ArrayIndices(vec![1, 2])
.eval(&json_books()) .eval(&json_books())
.unwrap(), .unwrap(),
JsonpathResult::Collection(vec![json_second_book(), json_third_book()]) JsonpathResult::Collection(vec![json_second_book(), json_third_book()])
@ -458,9 +453,13 @@ mod tests {
pub fn test_array_index() { pub fn test_array_index() {
let value = json!(["first", "second", "third", "forth", "fifth"]); let value = json!(["first", "second", "third", "forth", "fifth"]);
assert_eq!( assert_eq!(
Selector::ArrayIndex(vec![2]).eval(&value).unwrap(), Selector::ArrayIndex(2).eval(&value).unwrap(),
JsonpathResult::SingleEntry(json!("third")) JsonpathResult::SingleEntry(json!("third"))
); );
assert_eq!(
Selector::ArrayIndices(vec![2, 3]).eval(&value).unwrap(),
JsonpathResult::Collection(vec![json!("third"), json!("forth")])
);
} }
#[test] #[test]

View File

@ -50,7 +50,7 @@ fn selector(reader: &mut Reader) -> ParseResult<Selector> {
selector_wildcard, selector_wildcard,
selector_recursive_wildcard, selector_recursive_wildcard,
selector_recursive_key, selector_recursive_key,
selector_array_index, selector_array_index_or_array_indices,
selector_array_wildcard, selector_array_wildcard,
selector_array_slice, selector_array_slice,
selector_object_key_bracket, selector_object_key_bracket,
@ -60,7 +60,7 @@ fn selector(reader: &mut Reader) -> ParseResult<Selector> {
) )
} }
fn selector_array_index(reader: &mut Reader) -> Result<Selector, Error> { fn selector_array_index_or_array_indices(reader: &mut Reader) -> Result<Selector, Error> {
try_left_bracket(reader)?; try_left_bracket(reader)?;
let mut indexes = vec![]; let mut indexes = vec![];
let i = match natural(reader) { let i = match natural(reader) {
@ -94,7 +94,12 @@ fn selector_array_index(reader: &mut Reader) -> Result<Selector, Error> {
} }
} }
literal("]", reader)?; literal("]", reader)?;
Ok(Selector::ArrayIndex(indexes)) let selector = if indexes.len() == 1 {
Selector::ArrayIndex(*indexes.first().unwrap())
} else {
Selector::ArrayIndices(indexes)
};
Ok(selector)
} }
fn selector_array_wildcard(reader: &mut Reader) -> Result<Selector, Error> { fn selector_array_wildcard(reader: &mut Reader) -> Result<Selector, Error> {
@ -312,7 +317,7 @@ mod tests {
#[test] #[test]
pub fn test_query() { pub fn test_query() {
let expected_query = Query { let expected_query = Query {
selectors: vec![Selector::ArrayIndex(vec![2])], selectors: vec![Selector::ArrayIndex(2)],
}; };
assert_eq!(query(&mut Reader::new("$[2]")).unwrap(), expected_query); assert_eq!(query(&mut Reader::new("$[2]")).unwrap(), expected_query);
@ -338,7 +343,7 @@ mod tests {
selectors: vec![ selectors: vec![
Selector::NameChild("store".to_string()), Selector::NameChild("store".to_string()),
Selector::NameChild("book".to_string()), Selector::NameChild("book".to_string()),
Selector::ArrayIndex(vec![0]), Selector::ArrayIndex(0),
Selector::NameChild("title".to_string()), Selector::NameChild("title".to_string()),
], ],
}; };
@ -354,7 +359,7 @@ mod tests {
let expected_query = Query { let expected_query = Query {
selectors: vec![ selectors: vec![
Selector::RecursiveKey("book".to_string()), Selector::RecursiveKey("book".to_string()),
Selector::ArrayIndex(vec![2]), Selector::ArrayIndex(2),
], ],
}; };
assert_eq!( assert_eq!(
@ -423,26 +428,20 @@ mod tests {
#[test] #[test]
pub fn test_selector_array_index() { pub fn test_selector_array_index() {
let mut reader = Reader::new("[2]"); let mut reader = Reader::new("[2]");
assert_eq!( assert_eq!(selector(&mut reader).unwrap(), Selector::ArrayIndex(2));
selector(&mut reader).unwrap(),
Selector::ArrayIndex(vec![2])
);
assert_eq!(reader.state.cursor, 3); assert_eq!(reader.state.cursor, 3);
let mut reader = Reader::new("[0,1]"); let mut reader = Reader::new("[0,1]");
assert_eq!( assert_eq!(
selector(&mut reader).unwrap(), selector(&mut reader).unwrap(),
Selector::ArrayIndex(vec![0, 1]) Selector::ArrayIndices(vec![0, 1])
); );
assert_eq!(reader.state.cursor, 5); assert_eq!(reader.state.cursor, 5);
// you don't need to keep the exact string // you don't need to keep the exact string
// this is not part of the AST // this is not part of the AST
let mut reader = Reader::new(".[2]"); let mut reader = Reader::new(".[2]");
assert_eq!( assert_eq!(selector(&mut reader).unwrap(), Selector::ArrayIndex(2));
selector(&mut reader).unwrap(),
Selector::ArrayIndex(vec![2])
);
assert_eq!(reader.state.cursor, 4); assert_eq!(reader.state.cursor, 4);
} }