diff --git a/src/select/mod.rs b/src/select/mod.rs index d0d9387..f924e4b 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -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 { 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 { - 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 { @@ -139,13 +139,59 @@ impl Selector { } pub fn select_to(&self) -> result::Result { - 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()) + } + + pub fn map(&mut self, func: F) -> result::Result<&mut Self, String> + where F: FnOnce(Value) -> Option + { + self.value = func((&self.select()?).into()).map(|ref v| v.into()); + Ok(self) + } + + pub fn map_as(&mut self, func: F) -> result::Result<&mut Self, String> + where F: FnOnce(D) -> Option, + 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()) } - _ => Err("Path is empty".to_owned()) + _ => None + }; + Ok(self) + } + + pub fn get(&self) -> Value { + match &self.value { + Some(value) => value.into(), + _ => Value::Null } } -} \ No newline at end of file + + pub fn get_as(&self) -> result::Result { + 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"), + } + } +} diff --git a/tests/selector.rs b/tests/selector.rs index 595ee06..e86594e 100644 --- a/tests/selector.rs +++ b/tests/selector.rs @@ -1,5 +1,6 @@ extern crate jsonpath_lib as jsonpath; extern crate serde; +#[macro_use] extern crate serde_json; use serde::{Deserialize, Serialize}; @@ -101,4 +102,108 @@ fn selector_select_to() { let result = selector.select_to::>().unwrap(); assert_eq!(input_person()[0], result[0]); -} \ No newline at end of file +} + +fn _remove_name(v: Value) -> Option { + 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 { + 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) -> Option> { + 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, + })); +}