mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-05-05 14:12:14 +00:00
Added a new function 'map', 'map_as' to the Selector
This commit is contained in:
parent
765f04ce5d
commit
e2a6b13c9a
@ -1,5 +1,5 @@
|
||||
use std::{fmt, result};
|
||||
use std::ops::Deref;
|
||||
use std::result;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
@ -100,21 +100,21 @@ impl Selector {
|
||||
pub fn value_from(&mut self, serializable: &impl serde::ser::Serialize) -> result::Result<&mut Self, String> {
|
||||
let ref_value: RefValue = serializable
|
||||
.serialize(super::ref_value::ser::Serializer)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
.map_err(|e| e.to_string())?;
|
||||
self.value = Some(ref_value.into());
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn value_from_str(&mut self, json_str: &str) -> result::Result<&mut Self, String> {
|
||||
let value = serde_json::from_str(json_str)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
.map_err(|e| e.to_string())?;
|
||||
self.value(&value)
|
||||
}
|
||||
|
||||
fn jf(&self) -> result::Result<JsonValueFilter, String> {
|
||||
match &self.value {
|
||||
Some(v) => Ok(JsonValueFilter::new_from_value(v.clone())),
|
||||
_ => return Err("Empty value".to_owned())
|
||||
_ => return Err(SelectorErrorMessage::EmptyValue.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,12 +126,12 @@ impl Selector {
|
||||
jf.visit(node.clone());
|
||||
Ok(jf.take_value())
|
||||
}
|
||||
_ => Err("Empty path".to_owned())
|
||||
_ => Err(SelectorErrorMessage::EmptyPath.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_to_str(&self) -> result::Result<String, String> {
|
||||
serde_json::to_string(self.select()?.deref()).map_err(|e| format!("{:?}", e))
|
||||
serde_json::to_string(self.select()?.deref()).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
pub fn select_to_value(&self) -> result::Result<Value, String> {
|
||||
@ -139,13 +139,59 @@ impl Selector {
|
||||
}
|
||||
|
||||
pub fn select_to<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
|
||||
let mut jf = self.jf()?;
|
||||
match &self.node {
|
||||
Some(node) => {
|
||||
jf.visit(node.clone());
|
||||
T::deserialize(jf.take_value().deref()).map_err(|e| format!("{:?}", e))
|
||||
T::deserialize(self.select()?.deref()).map_err(|e| e.to_string())
|
||||
}
|
||||
_ => Err("Path is empty".to_owned())
|
||||
|
||||
pub fn map<F>(&mut self, func: F) -> result::Result<&mut Self, String>
|
||||
where F: FnOnce(Value) -> Option<Value>
|
||||
{
|
||||
self.value = func((&self.select()?).into()).map(|ref v| v.into());
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn map_as<F, D, S>(&mut self, func: F) -> result::Result<&mut Self, String>
|
||||
where F: FnOnce(D) -> Option<S>,
|
||||
D: serde::de::DeserializeOwned,
|
||||
S: serde::ser::Serialize
|
||||
{
|
||||
let ret = func(D::deserialize(self.select()?.deref()).map_err(|e| e.to_string())?)
|
||||
.map(|ref ser| ser.serialize(super::ref_value::ser::Serializer));
|
||||
|
||||
self.value = match ret {
|
||||
Some(ret) => match ret {
|
||||
Ok(v) => Some(v.into()),
|
||||
Err(e) => return Err(e.to_string())
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Value {
|
||||
match &self.value {
|
||||
Some(value) => value.into(),
|
||||
_ => Value::Null
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_as<T: serde::de::DeserializeOwned>(&self) -> result::Result<T, String> {
|
||||
match &self.value {
|
||||
Some(value) => T::deserialize(value.deref()).map_err(|e| e.to_string()),
|
||||
_ => Err(SelectorErrorMessage::EmptyValue.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum SelectorErrorMessage {
|
||||
EmptyValue,
|
||||
EmptyPath,
|
||||
}
|
||||
|
||||
impl fmt::Display for SelectorErrorMessage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
SelectorErrorMessage::EmptyValue => write!(f, "Empty value"),
|
||||
SelectorErrorMessage::EmptyPath => write!(f, "Empty path"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
extern crate jsonpath_lib as jsonpath;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -102,3 +103,107 @@ fn selector_select_to() {
|
||||
let result = selector.select_to::<Vec<Person>>().unwrap();
|
||||
assert_eq!(input_person()[0], result[0]);
|
||||
}
|
||||
|
||||
fn _remove_name(v: Value) -> Option<Value> {
|
||||
let r = match v {
|
||||
Value::Array(mut vec) => {
|
||||
for mut v in &mut vec {
|
||||
v.as_object_mut().unwrap().remove("name");
|
||||
}
|
||||
Value::Array(vec)
|
||||
}
|
||||
_ => Value::Null
|
||||
};
|
||||
Some(r)
|
||||
}
|
||||
|
||||
fn _change_phone_number(v: Value) -> Option<Value> {
|
||||
let r = match v {
|
||||
Value::Array(mut vec) => {
|
||||
let mut v = vec.pop().unwrap();
|
||||
v.as_object_mut().unwrap()
|
||||
.insert("phone".to_string(), Value::String("1234".to_string()));
|
||||
v
|
||||
}
|
||||
_ => Value::Null
|
||||
};
|
||||
Some(r)
|
||||
}
|
||||
|
||||
fn _rejuvenate(mut vec: Vec<Person>) -> Option<Vec<Person>> {
|
||||
for p in &mut vec {
|
||||
p.age = p.age - 10;
|
||||
}
|
||||
Some(vec)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selector_map_basic() {
|
||||
let mut selector = Selector::new();
|
||||
|
||||
let result = selector
|
||||
.path("$..[?(@.age > 40)]").unwrap()
|
||||
.value_from_str(input_str()).unwrap()
|
||||
.map(_remove_name).unwrap()
|
||||
.get();
|
||||
|
||||
assert_eq!(result, json!([
|
||||
{"phone": "++44 12341234", "age": 42},
|
||||
{"phone": "++55 111111", "age": 50},
|
||||
{"phone": "++55 12341234", "age": 51},
|
||||
]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selector_map_chain() {
|
||||
let mut selector = Selector::new();
|
||||
|
||||
let result = selector
|
||||
.path("$..[?(@.age > 40)]").unwrap()
|
||||
.value_from_str(input_str()).unwrap()
|
||||
.map(_remove_name).unwrap()
|
||||
.path("$..[?(@.age == 50)]").unwrap()
|
||||
.map(_change_phone_number).unwrap()
|
||||
.get();
|
||||
|
||||
assert_eq!(result, json!({
|
||||
"phone": "1234",
|
||||
"age": 50,
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selector_map_as_basic() {
|
||||
let mut selector = Selector::new();
|
||||
|
||||
let result = selector
|
||||
.path("$..[?(@.age > 40)]").unwrap()
|
||||
.value_from_str(input_str()).unwrap()
|
||||
.map_as(_rejuvenate).unwrap()
|
||||
.get();
|
||||
|
||||
assert_eq!(result, json!([
|
||||
{"name": "이름2", "phone": "++44 12341234", "age": 32},
|
||||
{"name": "이름3", "phone": "++55 111111", "age": 40},
|
||||
{"name": "이름4", "phone": "++55 12341234", "age": 41},
|
||||
]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selector_map_as_chain() {
|
||||
let mut selector = Selector::new();
|
||||
|
||||
let result = selector
|
||||
.path("$..[?(@.age > 40)]").unwrap()
|
||||
.value_from_str(input_str()).unwrap()
|
||||
.map_as(_rejuvenate).unwrap()
|
||||
.path("$..[?(@.age == 40)]").unwrap()
|
||||
.map(_change_phone_number).unwrap()
|
||||
.get();
|
||||
|
||||
assert_eq!(result, json!({
|
||||
"name": "이름3",
|
||||
"phone": "1234",
|
||||
"age": 40,
|
||||
}));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user