Skip to content
This repository was archived by the owner on Nov 14, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jsonpath_lib"
version = "0.2.6"
version = "0.2.7"
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"
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ pub fn delete(value: Value, path: &str) -> Result<Value, JsonPathError> {
/// 0
/// };
///
/// Some(json!(age))
/// Ok(Some(json!(age)))
/// }).unwrap();
///
/// assert_eq!(ret, json!({
Expand All @@ -467,7 +467,7 @@ pub fn delete(value: Value, path: &str) -> Result<Value, JsonPathError> {
/// ```
pub fn replace_with<F>(value: Value, path: &str, fun: &mut F) -> Result<Value, JsonPathError>
where
F: FnMut(Value) -> Option<Value>,
F: FnMut(Value) -> Result<Option<Value>, JsonPathError>,
{
let mut selector = SelectorMut::default();
let value = selector.str_path(path)?.value(value).replace_with(fun)?;
Expand Down
23 changes: 13 additions & 10 deletions src/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub enum JsonPathError {
EmptyValue,
Path(String),
Serde(String),
Replacement(String)
}

impl fmt::Debug for JsonPathError {
Expand All @@ -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))
}
}
}
Expand Down Expand Up @@ -780,11 +782,11 @@ pub struct SelectorMut {
value: Option<Value>,
}

fn replace_value<F: FnMut(Value) -> Option<Value>>(
fn replace_value<F: FnMut(Value) -> Result<Option<Value>, JsonPathError>>(
mut tokens: Vec<String>,
value: &mut Value,
fun: &mut F,
) {
) -> Result<(), JsonPathError> {
let mut target = value;

let last_index = tokens.len().saturating_sub(1);
Expand All @@ -796,26 +798,26 @@ fn replace_value<F: FnMut(Value) -> Option<Value>>(
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)
}
Value::Array(ref mut vec) => {
if let Ok(x) = token.parse::<usize>() {
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 {
Expand All @@ -831,6 +833,7 @@ fn replace_value<F: FnMut(Value) -> Option<Value>>(
break;
}
}
Ok(())
}

impl SelectorMut {
Expand Down Expand Up @@ -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<Vec<&Value>, JsonPathError> {
Expand All @@ -942,7 +945,7 @@ impl SelectorMut {
}
}

pub fn replace_with<F: FnMut(Value) -> Option<Value>>(
pub fn replace_with<F: FnMut(Value) -> Result<Option<Value>, JsonPathError>>(
&mut self,
fun: &mut F,
) -> Result<&mut Self, JsonPathError> {
Expand All @@ -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)?;
}
}

Expand Down
4 changes: 2 additions & 2 deletions tests/readme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ fn readme_selector_mut() {
0
};

Some(json!(age))
Ok(Some(json!(age)))
})
.unwrap()
.take()
Expand Down Expand Up @@ -522,7 +522,7 @@ fn readme_replace_with() {
0
};

Some(json!(age))
Ok(Some(json!(age)))
})
.unwrap();

Expand Down
23 changes: 21 additions & 2 deletions tests/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()
Expand Down Expand Up @@ -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();
Expand Down