diff --git a/.idea/runConfigurations/filter_step_in__trace.xml b/.idea/runConfigurations/filter_step_in__trace.xml
new file mode 100644
index 0000000..a3a5433
--- /dev/null
+++ b/.idea/runConfigurations/filter_step_in__trace.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/benches/example.json b/benches/example.json
new file mode 100644
index 0000000..cb88a7b
--- /dev/null
+++ b/benches/example.json
@@ -0,0 +1,37 @@
+{
+ "store": {
+ "book": [
+ {
+ "category": "reference",
+ "author": "Nigel Rees",
+ "title": "Sayings of the Century",
+ "price": 8.95
+ },
+ {
+ "category": "fiction",
+ "author": "Evelyn Waugh",
+ "title": "Sword of Honour",
+ "price": 12.99
+ },
+ {
+ "category": "fiction",
+ "author": "Herman Melville",
+ "title": "Moby Dick",
+ "isbn": "0-553-21311-3",
+ "price": 8.99
+ },
+ {
+ "category": "fiction",
+ "author": "J. R. R. Tolkien",
+ "title": "The Lord of the Rings",
+ "isbn": "0-395-19395-8",
+ "price": 22.99
+ }
+ ],
+ "bicycle": {
+ "color": "red",
+ "price": 19.95
+ }
+ },
+ "expensive": 10
+}
\ No newline at end of file
diff --git a/src/jsonpath/json_filter.rs b/src/jsonpath/json_filter.rs
index f4cd647..ef298da 100644
--- a/src/jsonpath/json_filter.rs
+++ b/src/jsonpath/json_filter.rs
@@ -1,4 +1,5 @@
use core::borrow::Borrow;
+use std::collections::HashMap;
use std::error::Error;
use std::rc::Rc;
use std::result;
@@ -11,8 +12,6 @@ use jsonpath::parser::{
ParseToken,
};
-use std::collections::HashMap;
-
enum CmpType {
Eq,
Ne,
@@ -340,11 +339,12 @@ enum ValueFilterKey {
struct ValueFilter {
vw: ValueWrapper,
last_key: Option,
+ filter_mode: bool,
}
impl ValueFilter {
- fn new(v: Value) -> Self {
- ValueFilter { vw: ValueWrapper::new(v), last_key: None }
+ fn new(v: Value, filter_mode: bool) -> Self {
+ ValueFilter { vw: ValueWrapper::new(v), last_key: None, filter_mode }
}
fn iter_to_value_vec<'a, I: Iterator- >(iter: I) -> Vec {
@@ -422,12 +422,17 @@ impl ValueFilter {
debug!("step_in_string");
trace!("step_in_string - before: {:?}", self.vw.val);
+ let filter_mode = self.filter_mode;
let v = match &mut self.vw.val {
Value::Array(v) => {
let vec: Vec = v.iter_mut()
.map(|v| {
if v.is_object() && v.as_object().unwrap().contains_key(key) {
- v.take()
+ if filter_mode {
+ v.take()
+ } else {
+ v.get_mut(key).unwrap().take()
+ }
} else {
Value::Null
}
@@ -479,17 +484,17 @@ impl JsonValueFilter {
fn push_value_filter(&mut self, from_current: bool) {
if from_current {
self.filter_stack.last()
- .map(|vf| ValueFilter::new(vf.vw.clone_val()))
+ .map(|vf| ValueFilter::new(vf.vw.clone_val(), from_current))
.and_then(|vf| Some(self.filter_stack.push(vf)));
} else {
let v: &Value = self.json.as_ref().borrow();
- self.filter_stack.push(ValueFilter::new(v.clone()));
+ self.filter_stack.push(ValueFilter::new(v.clone(), !from_current));
}
}
fn replace_filter_stack(&mut self, v: Value) {
if self.filter_stack.is_empty() {
- self.filter_stack.push(ValueFilter::new(v));
+ self.filter_stack.push(ValueFilter::new(v, false));
} else {
match self.filter_stack.last_mut() {
Some(vf) => {
@@ -991,9 +996,11 @@ impl ValueWrapper {
mod tests {
extern crate env_logger;
- use std::sync::{Once, ONCE_INIT};
- use jsonpath::parser::Parser;
use std::io::Read;
+ use std::sync::{Once, ONCE_INIT};
+
+ use jsonpath::parser::Parser;
+
use super::*;
static INIT: Once = ONCE_INIT;
@@ -1007,7 +1014,7 @@ mod tests {
fn new_value_filter(file: &str) -> ValueFilter {
let string = read_json(file);
let json: Value = serde_json::from_str(string.as_str()).unwrap();
- ValueFilter::new(json)
+ ValueFilter::new(json, false)
}
fn do_filter(path: &str, file: &str) -> JsonValueFilter {
@@ -1044,6 +1051,19 @@ mod tests {
let current = jf.step_in_str("friends");
assert_eq!(current.is_array(), true);
}
+ let mut jf = new_value_filter("./benches/data_obj.json");
+ {
+ jf.step_in_str("school");
+ jf.step_in_str("friends");
+ jf.step_in_all();
+ let current = jf.step_in_str("name");
+ let friends = json!([
+ "Millicent Norman",
+ "Vincent Cannon",
+ "Gray Berry"
+ ]);
+ assert_eq!(&friends, ¤t.val);
+ }
}
#[test]
@@ -1129,16 +1149,30 @@ mod tests {
assert_eq!(&friends, jf.current_value());
//
- // TODO 원본 json 순서여야 하나?
+ // TODO 원본 json 순서여야 하나? => serde_json preserve_order 피처를 enable 시켜야 함.
//
let jf = do_filter("$.friends[?(@.id >= 2 || @.id == 1)]", "./benches/data_obj.json");
- let friends = json!([
- { "id" : 2, "name" : "Gray Berry" },
- { "id" : 1, "name" : "Vincent Cannon" }
- ]);
- assert_eq!(&friends, jf.current_value());
+ let mut map = HashMap::new();
+ let mut val = jf.current_value().clone();
+ val.as_array_mut().unwrap().iter_mut().enumerate().for_each(|(i, v)| {
+ map.insert(i, v.take());
+ });
+ let friends = vec![map.get_mut(&0).unwrap().take(), map.get_mut(&1).unwrap().take()];
+ assert_eq!(&Value::Array(friends), jf.current_value());
let jf = do_filter("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json");
assert_eq!(&Value::Null, jf.current_value());
}
+
+ #[test]
+ fn example() {
+ let jf = do_filter("$.store.book[*].author", "./benches/example.json");
+ let ret = json!([
+ "Nigel Rees",
+ "Evelyn Waugh",
+ "Herman Melville",
+ "J. R. R. Tolkien"
+ ]);
+ assert_eq!(&ret, jf.current_value());
+ }
}
\ No newline at end of file