mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-06-14 08:31:25 +00:00
Selector struct 추가
This commit is contained in:
2
.idea/runConfigurations/all.xml
generated
2
.idea/runConfigurations/all.xml
generated
@ -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
12
.idea/runConfigurations/selector.xml
generated
Normal 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 """ />
|
||||
<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>
|
2
.idea/runConfigurations/serde.xml
generated
2
.idea/runConfigurations/serde.xml
generated
@ -3,7 +3,7 @@
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="command" value="test --package jsonpath_lib --test serde """ />
|
||||
<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 />
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
76
src/lib.rs
76
src/lib.rs
@ -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()
|
||||
}
|
@ -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
122
src/select/mod.rs
Normal 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
92
tests/selector.rs
Normal 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]);
|
||||
}
|
@ -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() {}
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user