mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-04-25 09:22:19 +00:00
compiled_path 인자 타입 변경, compute_path 로직 개선
This commit is contained in:
parent
fbb2b49ba0
commit
2e9e0ac6fc
@ -125,12 +125,13 @@ fn bench_select_to_compare_with_delete(b: &mut Bencher) {
|
|||||||
|
|
||||||
let mut selector = Selector::new();
|
let mut selector = Selector::new();
|
||||||
let _ = selector.str_path(get_path());
|
let _ = selector.str_path(get_path());
|
||||||
let _ = selector.value(json);
|
|
||||||
|
|
||||||
b.iter(move || {
|
b.iter(move || {
|
||||||
for _ in 1..100 {
|
for _ in 1..100 {
|
||||||
let _ = json.clone();
|
let json = json.clone();
|
||||||
let _ = selector.reset_value().select();
|
let mut s = Selector::new();
|
||||||
|
let _ = s.compiled_path(selector.node_ref().unwrap()).value(&json);
|
||||||
|
let _ = s.select();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -14,8 +14,8 @@ exclude = ["artifacts.json", "index.node"]
|
|||||||
neon-build = "0.2.0"
|
neon-build = "0.2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#jsonpath_lib = "0.2.0"
|
jsonpath_lib = "0.2.0"
|
||||||
jsonpath_lib = {path="../../"}
|
#jsonpath_lib = { path = "../../" }
|
||||||
neon = "0.2.0"
|
neon = "0.2.0"
|
||||||
neon-serde = "0.1.1"
|
neon-serde = "0.1.1"
|
||||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||||
|
@ -110,7 +110,7 @@ impl SelectorCls {
|
|||||||
|
|
||||||
fn select(&self) -> String {
|
fn select(&self) -> String {
|
||||||
let node = match &self.node {
|
let node = match &self.node {
|
||||||
Some(node) => node.clone(),
|
Some(node) => node,
|
||||||
None => panic!("{:?}", JsonPathError::EmptyPath)
|
None => panic!("{:?}", JsonPathError::EmptyPath)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ impl SelectorCls {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut selector = Selector::new();
|
let mut selector = Selector::new();
|
||||||
selector.compiled_path(node.clone());
|
selector.compiled_path(node);
|
||||||
selector.value(&value);
|
selector.value(&value);
|
||||||
match selector.select_as_str() {
|
match selector.select_as_str() {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
|
@ -175,12 +175,9 @@ pub fn compile(path: &str) -> impl FnMut(&Value) -> Result<Vec<&Value>, JsonPath
|
|||||||
match &node {
|
match &node {
|
||||||
Ok(node) => {
|
Ok(node) => {
|
||||||
let mut selector = Selector::new();
|
let mut selector = Selector::new();
|
||||||
//
|
selector.compiled_path(node).value(json).select()
|
||||||
// TODO remove node.clone()
|
|
||||||
//
|
|
||||||
selector.compiled_path(node.clone()).value(json).select()
|
|
||||||
}
|
}
|
||||||
Err(e) => Err(JsonPathError::Path(e.clone()))
|
Err(e) => Err(JsonPathError::Path(e.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use array_tool::vec::{Intersect, Union};
|
use array_tool::vec::{Intersect, Union};
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexMap;
|
||||||
use serde_json::{Number, Value};
|
use serde_json::{Number, Value};
|
||||||
|
|
||||||
use parser::parser::*;
|
use parser::parser::*;
|
||||||
@ -487,19 +487,21 @@ pub enum JsonPathError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Selector<'a> {
|
pub struct Selector<'a, 'b> {
|
||||||
node: Option<Node>,
|
node: Option<Node>,
|
||||||
|
node_ref: Option<&'b Node>,
|
||||||
value: Option<&'a Value>,
|
value: Option<&'a Value>,
|
||||||
tokens: Vec<ParseToken>,
|
tokens: Vec<ParseToken>,
|
||||||
terms: Vec<Option<ExprTerm<'a>>>,
|
terms: Vec<Option<ExprTerm<'a>>>,
|
||||||
current: Option<Vec<&'a Value>>,
|
current: Option<Vec<&'a Value>>,
|
||||||
selectors: Vec<Selector<'a>>,
|
selectors: Vec<Selector<'a, 'b>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Selector<'a> {
|
impl<'a, 'b> Selector<'a, 'b> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Selector {
|
Selector {
|
||||||
node: None,
|
node: None,
|
||||||
|
node_ref: None,
|
||||||
value: None,
|
value: None,
|
||||||
tokens: Vec::new(),
|
tokens: Vec::new(),
|
||||||
terms: Vec::new(),
|
terms: Vec::new(),
|
||||||
@ -510,12 +512,29 @@ impl<'a> Selector<'a> {
|
|||||||
|
|
||||||
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
||||||
debug!("path : {}", path);
|
debug!("path : {}", path);
|
||||||
|
|
||||||
|
if self.node_ref.is_some() {
|
||||||
|
self.node_ref.take();
|
||||||
|
}
|
||||||
|
|
||||||
self.node = Some(Parser::compile(path).map_err(|e| JsonPathError::Path(e))?);
|
self.node = Some(Parser::compile(path).map_err(|e| JsonPathError::Path(e))?);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compiled_path(&mut self, node: Node) -> &mut Self {
|
pub fn node_ref(&self) -> Option<&Node> {
|
||||||
self.node = Some(node);
|
if let Some(node) = &self.node {
|
||||||
|
Some(node)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compiled_path(&mut self, node: &'b Node) -> &mut Self {
|
||||||
|
if self.node.is_some() {
|
||||||
|
self.node.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.node_ref = Some(node);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,14 +549,21 @@ impl<'a> Selector<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn _select(&mut self) -> Result<(), JsonPathError> {
|
fn _select(&mut self) -> Result<(), JsonPathError> {
|
||||||
match self.node.take() {
|
if self.node_ref.is_some() {
|
||||||
Some(node) => {
|
let node_ref = self.node_ref.take().unwrap();
|
||||||
self.visit(&node);
|
self.visit(node_ref);
|
||||||
self.node = Some(node);
|
return Ok(());
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Err(JsonPathError::EmptyPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.node.is_none() {
|
||||||
|
return Err(JsonPathError::EmptyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = self.node.take().unwrap();
|
||||||
|
self.visit(&node);
|
||||||
|
self.node = Some(node);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_as<T: serde::de::DeserializeOwned>(&mut self) -> Result<Vec<T>, JsonPathError> {
|
pub fn select_as<T: serde::de::DeserializeOwned>(&mut self) -> Result<Vec<T>, JsonPathError> {
|
||||||
@ -743,7 +769,7 @@ impl<'a> Selector<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NodeVisitor for Selector<'a> {
|
impl<'a, 'b> NodeVisitor for Selector<'a, 'b> {
|
||||||
fn visit_token(&mut self, token: &ParseToken) {
|
fn visit_token(&mut self, token: &ParseToken) {
|
||||||
debug!("token: {:?}, stack: {:?}", token, self.tokens);
|
debug!("token: {:?}, stack: {:?}", token, self.tokens);
|
||||||
|
|
||||||
@ -1002,17 +1028,23 @@ impl SelectorMut {
|
|||||||
self.value.take()
|
self.value.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_paths(&self, result: &Vec<&Value>) -> Vec<Vec<String>> {
|
fn compute_paths(&self, mut result: Vec<&Value>) -> Vec<Vec<String>> {
|
||||||
fn _walk(origin: &Value, target: &Value, tokens: &mut Vec<String>, visited: &mut IndexSet<Vec<String>>) -> bool {
|
fn _walk(origin: &Value, target: &mut Vec<&Value>, tokens: &mut Vec<String>, visited: &mut IndexMap<*const Value, Vec<String>>) -> bool {
|
||||||
if visited.contains(tokens) {
|
trace!("{:?}, {:?}", target, tokens);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if std::ptr::eq(origin, target) {
|
if target.is_empty() {
|
||||||
debug!("tokens: {:?}", tokens);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target.retain(|t| {
|
||||||
|
if std::ptr::eq(origin, *t) {
|
||||||
|
visited.insert(*t, tokens.to_vec());
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
match origin {
|
match origin {
|
||||||
Value::Array(vec) => for (i, v) in vec.iter().enumerate() {
|
Value::Array(vec) => for (i, v) in vec.iter().enumerate() {
|
||||||
tokens.push(i.to_string());
|
tokens.push(i.to_string());
|
||||||
@ -1034,18 +1066,14 @@ impl SelectorMut {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut visited = IndexSet::new();
|
let mut visited = IndexMap::new();
|
||||||
|
|
||||||
if let Some(origin) = &self.value {
|
if let Some(origin) = &self.value {
|
||||||
for v in result {
|
let mut tokens = Vec::new();
|
||||||
let mut tokens = Vec::new();
|
_walk(origin, &mut result, &mut tokens, &mut visited);
|
||||||
if _walk(origin, v, &mut tokens, &mut visited) {
|
|
||||||
visited.insert(tokens);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visited.iter().map(|v| v.to_vec()).collect()
|
visited.iter().map(|(_, v)| v.to_vec()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(&mut self) -> Result<&mut Self, JsonPathError> {
|
pub fn delete(&mut self) -> Result<&mut Self, JsonPathError> {
|
||||||
@ -1053,21 +1081,24 @@ impl SelectorMut {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_with<F: FnMut(&Value) -> Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> {
|
pub fn replace_with<F: FnMut(&Value) -> Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> {
|
||||||
let mut selector = Selector::new();
|
if self.path.is_none() {
|
||||||
|
return Err(JsonPathError::EmptyPath);
|
||||||
if let Some(path) = self.path.take() {
|
|
||||||
selector.compiled_path(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let node = self.path.take().unwrap();
|
||||||
|
|
||||||
|
let mut selector = Selector::new();
|
||||||
|
selector.compiled_path(&node);
|
||||||
|
|
||||||
if let Some(value) = &self.value {
|
if let Some(value) = &self.value {
|
||||||
selector.value(value);
|
selector.value(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = selector.select();
|
let result = selector.select();
|
||||||
|
|
||||||
self.path = Some(selector.node.unwrap());
|
self.path = Some(node);
|
||||||
|
|
||||||
let paths = self.compute_paths(&result?);
|
let paths = self.compute_paths(result?);
|
||||||
|
|
||||||
if let Some(mut value) = self.value.take() {
|
if let Some(mut value) = self.value.take() {
|
||||||
for tokens in paths {
|
for tokens in paths {
|
||||||
|
@ -37,29 +37,4 @@ fn selector_mut() {
|
|||||||
.select().unwrap();
|
.select().unwrap();
|
||||||
|
|
||||||
assert_eq!(vec![&json!("a"), &json!("a"), &json!("a"), &json!("a"), &json!("a")], result);
|
assert_eq!(vec![&json!("a"), &json!("a"), &json!("a"), &json!("a"), &json!("a")], result);
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn selector_mut_delete_array() {
|
|
||||||
setup();
|
|
||||||
|
|
||||||
let json = serde_json::from_str(r#"{
|
|
||||||
"school": {
|
|
||||||
"friends": [
|
|
||||||
{"name": "친구1", "age": 20},
|
|
||||||
{"name": "친구2", "age": 20}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"friends": [
|
|
||||||
{"name": "친구3", "age": 30},
|
|
||||||
{"name": "친구4"}
|
|
||||||
]
|
|
||||||
}"#).unwrap();
|
|
||||||
|
|
||||||
let json1 = jsonpath::delete(json, "$..friends[0]").unwrap();
|
|
||||||
|
|
||||||
println!("{:?}", json1);
|
|
||||||
|
|
||||||
let mut json2 = jsonpath::delete(json1, "$..friends[1]").unwrap();
|
|
||||||
|
|
||||||
}
|
}
|
@ -88,7 +88,7 @@ pub fn compile(path: &str) -> JsValue {
|
|||||||
let cb = Closure::wrap(Box::new(move |js_value: JsValue| {
|
let cb = Closure::wrap(Box::new(move |js_value: JsValue| {
|
||||||
let mut selector = _Selector::new();
|
let mut selector = _Selector::new();
|
||||||
match &node {
|
match &node {
|
||||||
Ok(node) => selector.compiled_path(node.clone()),
|
Ok(node) => selector.compiled_path(node),
|
||||||
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone())))
|
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone())))
|
||||||
};
|
};
|
||||||
let json = match into_serde_json(&js_value) {
|
let json = match into_serde_json(&js_value) {
|
||||||
@ -120,7 +120,7 @@ pub fn selector(js_value: JsValue) -> JsValue {
|
|||||||
match Parser::compile(path.as_str()) {
|
match Parser::compile(path.as_str()) {
|
||||||
Ok(node) => {
|
Ok(node) => {
|
||||||
let mut selector = _Selector::new();
|
let mut selector = _Selector::new();
|
||||||
let _ = selector.compiled_path(node);
|
let _ = selector.compiled_path(&node);
|
||||||
match selector.value(&json).select() {
|
match selector.value(&json).select() {
|
||||||
Ok(ret) => match JsValue::from_serde(&ret) {
|
Ok(ret) => match JsValue::from_serde(&ret) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user