diff --git a/Cargo.toml b/Cargo.toml index 1f325d9a..13397f88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath_lib" -version = "0.2.6" +version = "0.2.7" authors = ["Changseok Han "] 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" diff --git a/src/lib.rs b/src/lib.rs index 55ac5194..e8f03f49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -450,7 +450,7 @@ pub fn delete(value: Value, path: &str) -> Result { /// 0 /// }; /// -/// Some(json!(age)) +/// Ok(Some(json!(age))) /// }).unwrap(); /// /// assert_eq!(ret, json!({ @@ -467,7 +467,7 @@ pub fn delete(value: Value, path: &str) -> Result { /// ``` pub fn replace_with(value: Value, path: &str, fun: &mut F) -> Result where - F: FnMut(Value) -> Option, + F: FnMut(Value) -> Result, JsonPathError>, { let mut selector = SelectorMut::default(); let value = selector.str_path(path)?.value(value).replace_with(fun)?; diff --git a/src/select/mod.rs b/src/select/mod.rs index 8b40787c..d87a578e 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -42,6 +42,7 @@ pub enum JsonPathError { EmptyValue, Path(String), Serde(String), + Replacement(String) } impl fmt::Debug for JsonPathError { @@ -57,6 +58,7 @@ impl fmt::Display for JsonPathError { JsonPathError::EmptyValue => f.write_str("json value not set"), JsonPathError::Path(msg) => f.write_str(&format!("path error: \n{}\n", msg)), JsonPathError::Serde(msg) => f.write_str(&format!("serde error: \n{}\n", msg)), + JsonPathError::Replacement(msg) => f.write_str(&format!("error occurred during jsonpath replacement: \n{}\n", msg)) } } } @@ -780,11 +782,11 @@ pub struct SelectorMut { value: Option, } -fn replace_value Option>( +fn replace_value Result, JsonPathError>>( mut tokens: Vec, value: &mut Value, fun: &mut F, -) { +) -> Result<(), JsonPathError> { let mut target = value; let last_index = tokens.len().saturating_sub(1); @@ -796,13 +798,13 @@ fn replace_value Option>( if is_last { if let Entry::Occupied(mut e) = map.entry(token) { let v = e.insert(Value::Null); - if let Some(res) = fun(v) { + if let Some(res) = fun(v)? { e.insert(res); } else { e.remove(); } } - return; + return Ok(()); } map.get_mut(&token) } @@ -810,12 +812,12 @@ fn replace_value Option>( if let Ok(x) = token.parse::() { if is_last { let v = std::mem::replace(&mut vec[x], Value::Null); - if let Some(res) = fun(v) { + if let Some(res) = fun(v)? { vec[x] = res; } else { vec.remove(x); } - return; + return Ok(()); } vec.get_mut(x) } else { @@ -831,6 +833,7 @@ fn replace_value Option>( break; } } + Ok(()) } impl SelectorMut { @@ -920,11 +923,11 @@ impl SelectorMut { } pub fn delete(&mut self) -> Result<&mut Self, JsonPathError> { - self.replace_with(&mut |_| Some(Value::Null)) + self.replace_with(&mut |_| Ok(Some(Value::Null))) } pub fn remove(&mut self) -> Result<&mut Self, JsonPathError> { - self.replace_with(&mut |_| None) + self.replace_with(&mut |_| Ok(None)) } fn select(&self) -> Result, JsonPathError> { @@ -942,7 +945,7 @@ impl SelectorMut { } } - pub fn replace_with Option>( + pub fn replace_with Result, JsonPathError>>( &mut self, fun: &mut F, ) -> Result<&mut Self, JsonPathError> { @@ -953,7 +956,7 @@ impl SelectorMut { if let Some(ref mut value) = &mut self.value { for tokens in paths { - replace_value(tokens, value, fun); + replace_value(tokens, value, fun)?; } } diff --git a/tests/readme.rs b/tests/readme.rs index b8a3786d..4942e492 100644 --- a/tests/readme.rs +++ b/tests/readme.rs @@ -224,7 +224,7 @@ fn readme_selector_mut() { 0 }; - Some(json!(age)) + Ok(Some(json!(age))) }) .unwrap() .take() @@ -522,7 +522,7 @@ fn readme_replace_with() { 0 }; - Some(json!(age)) + Ok(Some(json!(age))) }) .unwrap(); diff --git a/tests/selector.rs b/tests/selector.rs index 113f66ba..12fce4f7 100644 --- a/tests/selector.rs +++ b/tests/selector.rs @@ -3,7 +3,7 @@ extern crate jsonpath_lib as jsonpath; extern crate serde_json; use common::{read_json, setup}; -use jsonpath::{Parser, Selector, SelectorMut}; +use jsonpath::{Parser, Selector, SelectorMut, JsonPathError}; use serde_json::Value; mod common; @@ -23,7 +23,7 @@ fn selector_mut() { if let Value::Number(n) = v { nums.push(n.as_f64().unwrap()); } - Some(Value::String("a".to_string())) + Ok(Some(Value::String("a".to_string()))) }) .unwrap() .take() @@ -54,6 +54,25 @@ fn selector_mut() { ); } +#[test] +fn selector_mut_err() { + setup(); + + let mut selector_mut = SelectorMut::default(); + let result = selector_mut + .str_path(r#"$.store..price"#) + .unwrap() + .value(read_json("./benchmark/example.json")) + .replace_with(&mut |_| { + Err(JsonPathError::EmptyValue) + }); + + assert_eq!( + result.is_err(), + true + ); +} + #[test] fn selector_node_ref() { let node = Parser::compile("$.*").unwrap();