Selector struct 추가

This commit is contained in:
freestrings
2019-04-07 23:34:16 +09:00
parent d955a1632c
commit 30aa38379a
11 changed files with 294 additions and 65 deletions

View File

@ -3,7 +3,7 @@
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package jsonpath_lib" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="nocapture" value="true" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />

12
.idea/runConfigurations/selector.xml generated Normal file
View File

@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="selector" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package jsonpath_lib --test selector &quot;&quot;" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@ -3,7 +3,7 @@
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package jsonpath_lib --test serde &quot;&quot;" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="true" />
<option name="nocapture" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />

View File

@ -39,8 +39,6 @@ To enjoy Rust!
- [rust - jsonpath::selector_as\<T: `serde::de::DeserializeOwned`\>(json: &serde_json::value::Value)](#rust---jsonpathselector_ast-serdededeserializeownedjson-serde_jsonvaluevalue)
- [rust - examples](https://github.com/freestrings/jsonpath/wiki/rust-examples)
[With AWS API Gateway](#)
[Simple time check - webassembly](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck---jsonpath-wasm)
[Simple time check - native addon for NodeJs](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck-jsonpath-native)

View File

@ -3,6 +3,7 @@ extern crate jsonpath_lib as jsonpath;
extern crate serde;
extern crate serde_json;
extern crate test;
extern crate bencher;
use std::io::Read;
@ -10,6 +11,8 @@ use serde::Deserialize;
use serde_json::Value;
use self::test::Bencher;
use jsonpath::ref_value::model::RefValue;
use serde::ser::Serialize;
fn read_json(path: &str) -> String {
let mut f = std::fs::File::open(path).unwrap();
@ -102,3 +105,24 @@ fn bench_select_as(b: &mut Bencher) {
}
});
}
#[bench]
fn bench_serde_ser(b: &mut Bencher) {
let json = get_json();
b.iter(move || {
for _ in 1..100 {
let _: RefValue = json.serialize(jsonpath::ref_value::ser::Serializer).unwrap().into();
}
});
}
#[bench]
fn bench_serde_de(b: &mut Bencher) {
let json_string = get_string();
let json_str = json_string.as_str();
b.iter(move || for _ in 1..100 {
let _: RefValue = serde_json::from_str(json_str).unwrap();
});
}

View File

@ -158,6 +158,7 @@
//! assert_eq!(ret, json);
//! ```
extern crate core;
extern crate env_logger;
extern crate indexmap;
#[macro_use]
@ -166,36 +167,21 @@ extern crate log;
extern crate serde;
extern crate serde_json;
use std::error::Error;
use std::ops::Deref;
use core::borrow::BorrowMut;
use std::result;
use serde_json::Value;
use filter::value_filter::JsonValueFilter;
use parser::parser::{NodeVisitor, Parser};
use ref_value::model::RefValueWrapper;
#[doc(hidden)]
pub mod parser;
#[doc(hidden)]
pub mod filter;
#[doc(hidden)]
pub mod ref_value;
#[doc(hidden)]
pub mod select;
fn query_from_str(json: &str, path: &str) -> result::Result<JsonValueFilter, String> {
let mut jf = JsonValueFilter::new(json)?;
let mut parser = Parser::new(path);
parser.parse(&mut jf)?;
Ok(jf)
}
fn query_from_json_wrapper(json_wrapper: RefValueWrapper, path: &str) -> result::Result<JsonValueFilter, String> {
let mut jf = JsonValueFilter::new_from_value(json_wrapper);
let mut parser = Parser::new(path);
parser.parse(&mut jf)?;
Ok(jf)
}
pub use select::Selector;
/// It is a highorder function that compile a JsonPath then returns a function.
///
@ -227,17 +213,13 @@ fn query_from_json_wrapper(json_wrapper: RefValueWrapper, path: &str) -> result:
/// assert_eq!(json, ret);
/// ```
pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> result::Result<Value, String> + 'a {
let mut parser = Parser::new(path);
let node = parser.compile();
let mut selector = select::Selector::new();
let _ = selector.path(path);
let mut selector = Box::new(selector);
move |json| {
match &node {
Ok(n) => {
let mut jf = JsonValueFilter::new_from_value(json.into());
jf.visit(n.clone());
Ok((&jf.take_value()).into())
}
Err(e) => Err(e.clone())
}
let s: &mut select::Selector = selector.borrow_mut();
let _ = s.value(json.into());
s.select_to_value()
}
}
@ -277,11 +259,13 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> result::Result<Value,
/// ]);
/// assert_eq!(json, ret);
/// ```
pub fn selector(json: &Value) -> impl FnMut(&str) -> result::Result<Value, String> {
let wrapper: RefValueWrapper = json.into();
move |path: &str| {
let mut jf = query_from_json_wrapper(wrapper.clone(), path)?;
Ok((&jf.take_value()).into())
pub fn selector<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result<Value, String> {
let mut selector = select::Selector::new();
let _ = selector.value(json.into());
let mut selector = Box::new(selector);
move |path: &'a str| {
let s: &mut select::Selector = selector.borrow_mut();
s.path(path)?.select_to_value()
}
}
@ -331,15 +315,15 @@ pub fn selector(json: &Value) -> impl FnMut(&str) -> result::Result<Value, Strin
/// assert_eq!(json, ret);
/// ```
pub fn selector_as<T: serde::de::DeserializeOwned>(json: &Value) -> impl FnMut(&str) -> result::Result<T, String> {
let wrapper: RefValueWrapper = json.into();
let mut selector = select::Selector::new();
let _ = selector.value(json.into());
move |path: &str| {
let mut jf = query_from_json_wrapper(wrapper.clone(), path)?;
T::deserialize(jf.take_value().deref()).map_err(|e| format!("{:?}", e))
selector.path(path)?.select_to()
}
}
#[deprecated(since = "0.1.4", note = "Please use the selector function instead")]
pub fn reader(json: &Value) -> impl FnMut(&str) -> result::Result<Value, String> {
pub fn reader<'a>(json: &Value) -> impl FnMut(&'a str) -> result::Result<Value, String> {
selector(json)
}
@ -370,8 +354,8 @@ pub fn reader(json: &Value) -> impl FnMut(&str) -> result::Result<Value, String>
/// assert_eq!(json, ret);
/// ```
pub fn select(json: &Value, path: &str) -> result::Result<Value, String> {
let mut jf = query_from_json_wrapper(json.into(), path)?;
Ok((&jf.take_value()).into())
let mut selector = select::Selector::new();
selector.path(path)?.value(json.into())?.select_to_value()
}
#[deprecated(since = "0.1.4", note = "Please use the select function instead")]
@ -408,8 +392,10 @@ pub fn select_str(json: &str, path: &str) -> result::Result<String, String> {
/// assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
/// ```
pub fn select_as_str(json: &str, path: &str) -> result::Result<String, String> {
let mut jf = query_from_str(json, path)?;
serde_json::to_string(&jf.take_value().deref()).map_err(|e| e.description().to_string())
select::Selector::new()
.path(path)?
.value_from_str(json)?
.select_to_str()
}
/// Select a JsonObject. it return a deserialized instance of type `T`
@ -451,6 +437,8 @@ pub fn select_as_str(json: &str, path: &str) -> result::Result<String, String> {
/// assert_eq!(person, ret);
/// ```
pub fn select_as<T: serde::de::DeserializeOwned>(json: &str, path: &str) -> result::Result<T, String> {
let mut jf = query_from_str(json, path)?;
T::deserialize(jf.take_value().deref()).map_err(|e| e.description().to_string())
select::Selector::new()
.path(path)?
.value_from_str(json)?
.select_to()
}

View File

@ -245,6 +245,15 @@ impl Into<RefValueWrapper> for RefValue {
}
}
impl Into<RefValue> for &Value {
fn into(self) -> RefValue {
match self.serialize(super::ser::Serializer) {
Ok(v) => v,
Err(e) => panic!("Error Value into RefValue: {:?}", e)
}
}
}
impl Into<RefValueWrapper> for &Value {
fn into(self) -> RefValueWrapper {
match self.serialize(super::ser::Serializer) {

122
src/select/mod.rs Normal file
View File

@ -0,0 +1,122 @@
use std::ops::Deref;
use std::result;
use serde_json::Value;
use super::filter::value_filter::*;
use super::parser::parser::*;
use super::ref_value::model::*;
/// Utility structure. Functions like jsonpath :: selector or jsonpath :: compile are also implemented using this structure.
///
/// ```rust
/// extern crate jsonpath_lib as jsonpath;
/// extern crate serde;
/// #[macro_use] extern crate serde_json;
///
/// use serde::{Deserialize, Serialize};
///
/// #[derive(Deserialize, PartialEq, Debug)]
/// struct Person {
/// name: String,
/// age: u8,
/// phones: Vec<String>,
/// }
///
/// let ret: Person = jsonpath::select_as(r#"
/// {
/// "person":
/// {
/// "name": "Doe John",
/// "age": 44,
/// "phones": [
/// "+44 1234567",
/// "+44 2345678"
/// ]
/// }
/// }
/// "#, "$.person").unwrap();
///
/// let person = Person {
/// name: "Doe John".to_owned(),
/// age: 44,
/// phones: vec!["+44 1234567".to_owned(), "+44 2345678".to_owned()],
/// };
///
/// assert_eq!(person, ret);
/// ```
pub struct Selector {
pub(crate) node: Option<Node>,
pub(crate) value: Option<RefValueWrapper>,
}
impl Selector {
pub fn new() -> Self {
Selector { node: None, value: None }
}
pub fn path(&mut self, path: &str) -> result::Result<&mut Self, String> {
let mut parser = Parser::new(path);
self.node = Some(parser.compile()?);
Ok(self)
}
pub fn value(&mut self, ref_value: RefValue) -> result::Result<&mut Self, String> {
self.value = Some(ref_value.into());
Ok(self)
}
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))?;
self.value(ref_value)
}
pub fn value_from_str(&mut self, json_str: &str) -> result::Result<&mut Self, String> {
let ref_value: RefValue = serde_json::from_str(json_str)
.map_err(|e| format!("{:?}", e))?;
self.value(ref_value)
}
fn jf(&mut self) -> result::Result<JsonValueFilter, String> {
match &self.value {
Some(v) => Ok(JsonValueFilter::new_from_value(v.clone())),
_ => return Err("Value is empty".to_owned())
}
}
pub fn select_to_str(&mut self) -> result::Result<String, String> {
let mut jf = self.jf()?;
match &mut self.node {
Some(node) => {
jf.visit(node.clone());
return serde_json::to_string(jf.take_value().deref()).map_err(|e| format!("{:?}", e));
}
_ => return Err("Path is empty".to_owned())
};
}
pub fn select_to_value(&mut self) -> result::Result<Value, String> {
let mut jf = self.jf()?;
match &mut self.node {
Some(node) => {
jf.visit(node.clone());
Ok((&jf.take_value()).into())
}
_ => Err("Path is empty".to_owned())
}
}
pub fn select_to<T: serde::de::DeserializeOwned>(&mut self) -> result::Result<T, String> {
let mut jf = self.jf()?;
match &mut self.node {
Some(node) => {
jf.visit(node.clone());
T::deserialize(jf.take_value().deref()).map_err(|e| format!("{:?}", e))
}
_ => Err("Path is empty".to_owned())
}
}
}

92
tests/selector.rs Normal file
View File

@ -0,0 +1,92 @@
extern crate jsonpath_lib as jsonpath;
extern crate serde;
extern crate serde_json;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use jsonpath::Selector;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Person {
name: String,
age: u8,
phone: String,
}
fn input_str() -> &'static str {
r#"[
{
"name": "이름1",
"age": 40,
"phone": "+33 12341234"
},
{
"name": "이름2",
"age": 42,
"phone": "++44 12341234"
}
]"#
}
fn input_json() -> Value {
serde_json::from_str(input_str()).unwrap()
}
fn input_person() -> Vec<Person> {
serde_json::from_str(input_str()).unwrap()
}
#[test]
fn selector_value_from() {
let result = Selector::new()
.path("$..[?(@.age > 40)]").unwrap()
.value_from(&input_person()).unwrap()
.select_to::<Vec<Person>>().unwrap();
assert_eq!(input_person()[1], result[0]);
}
#[test]
fn selector_value() {
let result = Selector::new()
.path("$..[?(@.age > 40)]").unwrap()
.value((&input_json()).into()).unwrap()
.select_to_value().unwrap();
assert_eq!(input_json()[1], result[0]);
}
#[test]
fn selector_value_from_str() {
let result = Selector::new()
.path("$..[?(@.age > 40)]").unwrap()
.value_from_str(input_str()).unwrap()
.select_to_value().unwrap();
assert_eq!(input_json()[1], result[0]);
}
#[test]
fn selector_select_to() {
let mut selector = Selector::new();
let result = selector
.path("$..[?(@.age > 40)]").unwrap()
.value_from_str(input_str()).unwrap()
.select_to_value().unwrap();
assert_eq!(input_json()[1], result[0]);
let result = selector.select_to_str().unwrap();
assert_eq!(serde_json::to_string(&vec![&input_json()[1].clone()]).unwrap(), result);
let result = selector.select_to::<Vec<Person>>().unwrap();
assert_eq!(input_person()[1], result[0]);
let _ = selector.path("$..[?(@.age == 40)]");
let result = selector.select_to_value().unwrap();
assert_eq!(input_json()[0], result[0]);
let result = selector.select_to_str().unwrap();
assert_eq!(serde_json::to_string(&vec![&input_json()[0].clone()]).unwrap(), result);
let result = selector.select_to::<Vec<Person>>().unwrap();
assert_eq!(input_person()[0], result[0]);
}

View File

@ -120,14 +120,6 @@ pub fn compile(path: &str) -> JsValue {
ret
}
///
/// deprecated. use selector
///
#[wasm_bindgen]
pub fn reader(js_value: JsValue) -> JsValue {
selector(js_value)
}
#[wasm_bindgen]
pub fn selector(js_value: JsValue) -> JsValue {
let json = match js_value.as_f64() {
@ -167,13 +159,5 @@ pub fn select(js_value: JsValue, path: &str) -> JsValue {
}
}
///
/// deprecated. use select
///
#[wasm_bindgen]
pub fn read(js_value: JsValue, path: &str) -> JsValue {
select(js_value, path)
}
#[wasm_bindgen]
pub fn testa() {}

View File

@ -36,7 +36,7 @@ function initEvent() {
}
function read() {
let ret = jsonpath.read(getTextarea().value, getJsonpathInput().value);
let ret = jsonpath.select(getTextarea().value, getJsonpathInput().value);
if(typeof ret === 'string') {
getReadResult().innerText = ret;
} else {