mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-05-10 08:17:12 +00:00
return error if key or index not found
This commit is contained in:
parent
021f57b323
commit
f997d5252b
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jsonpath_lib-fl"
|
name = "jsonpath_lib-fl"
|
||||||
version = "0.2.6"
|
version = "0.2.7"
|
||||||
authors = ["Changseok Han <freestrings@gmail.com>"]
|
authors = ["Changseok Han <freestrings@gmail.com>"]
|
||||||
|
|
||||||
description = "It is JsonPath engine written in Rust. it provide a similar API interface in Webassembly and Javascript too. - Webassembly Demo: https://freestrings.github.io/jsonpath"
|
description = "It is JsonPath engine written in Rust. it provide a similar API interface in Webassembly and Javascript too. - Webassembly Demo: https://freestrings.github.io/jsonpath"
|
||||||
|
@ -457,9 +457,10 @@ pub struct Selector<'a, 'b> {
|
|||||||
current: Option<Vec<&'a Value>>,
|
current: Option<Vec<&'a Value>>,
|
||||||
values: Option<Box<dyn ExactSizeIterator<Item = &'a Value> + 'a>>,
|
values: Option<Box<dyn ExactSizeIterator<Item = &'a Value> + 'a>>,
|
||||||
chose_indices: Vec<usize>,
|
chose_indices: Vec<usize>,
|
||||||
|
// true if values haven't been found by key or index in JValue
|
||||||
|
not_found_by_key_index: bool,
|
||||||
selectors: Vec<Selector<'a, 'b>>,
|
selectors: Vec<Selector<'a, 'b>>,
|
||||||
selector_filter: FilterTerms<'a>,
|
selector_filter: FilterTerms<'a>,
|
||||||
should_flatten_arrays: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Selector<'a, 'b> {
|
impl<'a, 'b> Selector<'a, 'b> {
|
||||||
@ -470,14 +471,6 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
||||||
debug!("path : {}", path);
|
debug!("path : {}", path);
|
||||||
|
|
||||||
let path = match path.strip_suffix('!') {
|
|
||||||
Some(path) => {
|
|
||||||
self.should_flatten_arrays = true;
|
|
||||||
path
|
|
||||||
}
|
|
||||||
None => path,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.node_ref.take();
|
self.node_ref.take();
|
||||||
self.node = Some(Parser::compile(path).map_err(JsonPathError::Path)?);
|
self.node = Some(Parser::compile(path).map_err(JsonPathError::Path)?);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
@ -523,7 +516,12 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
if self.node_ref.is_some() {
|
if self.node_ref.is_some() {
|
||||||
let node_ref = self.node_ref.take().unwrap();
|
let node_ref = self.node_ref.take().unwrap();
|
||||||
self.visit(node_ref);
|
self.visit(node_ref);
|
||||||
return Ok(());
|
|
||||||
|
return if self.not_found_by_key_index {
|
||||||
|
Err(JsonPathError::EmptyValue)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.node.is_none() {
|
if self.node.is_none() {
|
||||||
@ -534,8 +532,12 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
self.visit(&node);
|
self.visit(&node);
|
||||||
self.node = Some(node);
|
self.node = Some(node);
|
||||||
|
|
||||||
|
if self.not_found_by_key_index {
|
||||||
|
Err(JsonPathError::EmptyValue)
|
||||||
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn select_as<T: serde::de::DeserializeOwned>(&mut self) -> Result<Vec<T>, JsonPathError> {
|
pub fn select_as<T: serde::de::DeserializeOwned>(&mut self) -> Result<Vec<T>, JsonPathError> {
|
||||||
self._select()?;
|
self._select()?;
|
||||||
@ -570,27 +572,7 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
self._select()?;
|
self._select()?;
|
||||||
|
|
||||||
match &self.current {
|
match &self.current {
|
||||||
Some(r) => {
|
Some(r) => Ok(r.to_vec()),
|
||||||
if self.should_flatten_arrays {
|
|
||||||
if r.len() != 1 {
|
|
||||||
let value = r.iter().map(|&v| v.clone()).collect::<Vec<_>>();
|
|
||||||
return Err(JsonPathError::CantFlatten(value));
|
|
||||||
}
|
|
||||||
let value = r[0];
|
|
||||||
|
|
||||||
return match value {
|
|
||||||
Value::Array(array) => {
|
|
||||||
let result: Vec<&Value> = array.iter().map(|v| v).collect::<Vec<_>>();
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let value = r.iter().map(|&v| v.clone()).collect::<Vec<_>>();
|
|
||||||
Err(JsonPathError::CantFlatten(value))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Ok(r.to_vec())
|
|
||||||
}
|
|
||||||
_ => Err(JsonPathError::EmptyValue),
|
_ => Err(JsonPathError::EmptyValue),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,6 +651,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
self.selector_filter.collect_all(&self.current, values);
|
self.selector_filter.collect_all(&self.current, values);
|
||||||
|
|
||||||
self.current = current;
|
self.current = current;
|
||||||
|
self.update_not_found_by_current();
|
||||||
|
|
||||||
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
||||||
}
|
}
|
||||||
self.tokens.push(array_token.unwrap());
|
self.tokens.push(array_token.unwrap());
|
||||||
@ -706,6 +690,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
self.selector_filter.pop_term();
|
self.selector_filter.pop_term();
|
||||||
|
|
||||||
self.current = current;
|
self.current = current;
|
||||||
|
self.update_not_found_by_current();
|
||||||
|
|
||||||
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -717,6 +703,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
|
|
||||||
self.selector_filter.pop_term();
|
self.selector_filter.pop_term();
|
||||||
self.current = current;
|
self.current = current;
|
||||||
|
self.update_not_found_by_current();
|
||||||
|
|
||||||
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -743,6 +731,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
self.current = current;
|
self.current = current;
|
||||||
|
self.update_not_found_by_current();
|
||||||
|
|
||||||
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
||||||
}
|
}
|
||||||
ExprTerm::String(key) => {
|
ExprTerm::String(key) => {
|
||||||
@ -753,6 +743,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
.collect_next_with_str(&self.current, values, &[key]);
|
.collect_next_with_str(&self.current, values, &[key]);
|
||||||
|
|
||||||
self.current = current;
|
self.current = current;
|
||||||
|
self.update_not_found_by_current();
|
||||||
|
|
||||||
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
||||||
}
|
}
|
||||||
ExprTerm::Json(rel, _, v) => {
|
ExprTerm::Json(rel, _, v) => {
|
||||||
@ -763,6 +755,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
} else {
|
} else {
|
||||||
self.current = Some(v);
|
self.current = Some(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.update_not_found_by_current();
|
||||||
}
|
}
|
||||||
ExprTerm::Bool(false) => {
|
ExprTerm::Bool(false) => {
|
||||||
self.current = Some(vec![]);
|
self.current = Some(vec![]);
|
||||||
@ -843,6 +837,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
self.current = current;
|
self.current = current;
|
||||||
|
self.update_not_found_by_current();
|
||||||
|
|
||||||
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -876,6 +872,8 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
self.selector_filter
|
self.selector_filter
|
||||||
.collect_next_with_str(&self.current, values, keys);
|
.collect_next_with_str(&self.current, values, keys);
|
||||||
self.current = current;
|
self.current = current;
|
||||||
|
self.update_not_found_by_current();
|
||||||
|
|
||||||
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
self.chose_indices.extend(chose_indices.unwrap_or_default());
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@ -1031,6 +1029,14 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_not_found_by_current(&mut self) {
|
||||||
|
println!("current: {:?}", self.current);
|
||||||
|
|
||||||
|
if let Some(values) = &self.current {
|
||||||
|
self.not_found_by_key_index |= values.is_empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn chose_indices(self) -> Vec<usize> {
|
pub fn chose_indices(self) -> Vec<usize> {
|
||||||
self.chose_indices
|
self.chose_indices
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ fn selector() {
|
|||||||
{
|
{
|
||||||
let json = selector(path).unwrap();
|
let json = selector(path).unwrap();
|
||||||
compare_result(json, target);
|
compare_result(json, target);
|
||||||
};
|
}
|
||||||
|
|
||||||
let json_obj = read_json("./benchmark/data_obj.json");
|
let json_obj = read_json("./benchmark/data_obj.json");
|
||||||
let mut selector = jsonpath::selector(&json_obj);
|
let mut selector = jsonpath::selector(&json_obj);
|
||||||
@ -94,7 +94,7 @@ fn selector_as() {
|
|||||||
{
|
{
|
||||||
let json = selector(path).unwrap();
|
let json = selector(path).unwrap();
|
||||||
assert_eq!(json, target);
|
assert_eq!(json, target);
|
||||||
};
|
}
|
||||||
|
|
||||||
let json_obj = read_json("./benchmark/data_obj.json");
|
let json_obj = read_json("./benchmark/data_obj.json");
|
||||||
let mut selector = jsonpath::selector_as::<Friend>(&json_obj);
|
let mut selector = jsonpath::selector_as::<Friend>(&json_obj);
|
||||||
|
@ -54,6 +54,7 @@ fn return_type_for_child_object_matched() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn return_type_for_child_object_not_matched() {
|
fn return_type_for_child_object_not_matched() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ fn iter_test() {
|
|||||||
struct T {
|
struct T {
|
||||||
pub value: Rc<Value>,
|
pub value: Rc<Value>,
|
||||||
pub tt: i32,
|
pub tt: i32,
|
||||||
};
|
}
|
||||||
|
|
||||||
let t = Value::Array(vec![
|
let t = Value::Array(vec![
|
||||||
Value::String(String::from("vv")),
|
Value::String(String::from("vv")),
|
||||||
@ -177,14 +177,16 @@ fn iter_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flattening_test() {
|
fn test_not_found_by_index() {
|
||||||
let array = vec![1, 2, 3, 4, 5];
|
let array = vec![1, 2, 3, 4, 5];
|
||||||
let json_array = json!(array);
|
let haystack = json!(array);
|
||||||
let haystack = json!([json_array]);
|
let result = jsonpath::select(&haystack, "$.[6]");
|
||||||
let result = jsonpath::select(&haystack, "$.[0]!").unwrap();
|
assert!(result.is_err());
|
||||||
assert_eq!(result, array);
|
}
|
||||||
|
|
||||||
let haystack = json!({ "array": array });
|
#[test]
|
||||||
let result = jsonpath::select(&haystack, "$.array!").unwrap();
|
fn test_not_found_by_key() {
|
||||||
assert_eq!(result, array);
|
let haystack = json!({"asd": 1});
|
||||||
|
let result = jsonpath::select(&haystack, "$.aaa");
|
||||||
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user