From e02db88d20824832c8ad44c1b51c419285351343 Mon Sep 17 00:00:00 2001 From: freestrings Date: Sun, 24 Feb 2019 23:03:42 +0900 Subject: [PATCH] =?UTF-8?q?CmpCondType=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/runConfigurations/filter_op___trace.xml | 14 +++++ src/jsonpath/json_filter.rs | 55 +++++++++++++++---- 2 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 .idea/runConfigurations/filter_op___trace.xml diff --git a/.idea/runConfigurations/filter_op___trace.xml b/.idea/runConfigurations/filter_op___trace.xml new file mode 100644 index 0000000..c86bd9c --- /dev/null +++ b/.idea/runConfigurations/filter_op___trace.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/src/jsonpath/json_filter.rs b/src/jsonpath/json_filter.rs index 54d578e..f4cd647 100644 --- a/src/jsonpath/json_filter.rs +++ b/src/jsonpath/json_filter.rs @@ -22,6 +22,11 @@ enum CmpType { Le, } +enum CmpCondType { + And, + Or, +} + trait PrivCmp { fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool; @@ -256,12 +261,19 @@ impl TermContext { } } - fn cmp_cond(&mut self, other: &mut TermContext, cmp_fn: F) -> TermContext { + fn cmp_cond(&mut self, other: &mut TermContext, cmp_cond_type: CmpCondType) -> TermContext { match self { TermContext::Constants(et) => { match other { TermContext::Constants(oet) => { - TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, false))) + match cmp_cond_type { + CmpCondType::Or => { + TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpOr, false))) + } + CmpCondType::And => { + TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpAnd, false))) + } + } } TermContext::Json(_, v) => { TermContext::Json(None, ValueWrapper::new(v.clone_val())) @@ -271,7 +283,10 @@ impl TermContext { TermContext::Json(_, v) => { match other { TermContext::Json(_, ov) => { - TermContext::Json(None, v.union(ov)) + match cmp_cond_type { + CmpCondType::Or => TermContext::Json(None, v.union(ov)), + CmpCondType::And => TermContext::Json(None, v.intersect(ov)), + } } _ => { TermContext::Json(None, ValueWrapper::new(v.clone_val())) @@ -306,11 +321,11 @@ impl TermContext { } fn and(&mut self, other: &mut TermContext) -> TermContext { - self.cmp_cond(other, CmpAnd) + self.cmp_cond(other, CmpCondType::And) } fn or(&mut self, other: &mut TermContext) -> TermContext { - self.cmp_cond(other, CmpOr) + self.cmp_cond(other, CmpCondType::Or) } } @@ -554,10 +569,10 @@ impl NodeVisitor for JsonValueFilter { match self.token_stack.pop() { Some(ParseToken::In) => { vf.step_in_all(); - }, + } Some(ParseToken::Leaves) => { vf.step_leaves_all(); - }, + } _ => {} } } @@ -570,10 +585,10 @@ impl NodeVisitor for JsonValueFilter { match self.token_stack.pop() { Some(ParseToken::In) => { vf.step_in_string(&key); - }, + } Some(ParseToken::Leaves) => { vf.step_leaves(&key); - }, + } _ => {} } } @@ -602,6 +617,8 @@ impl NodeVisitor for JsonValueFilter { self.term_stack.push(tc); } } + + trace!("filter - {:?}", self.term_stack) } ParseToken::Number(v) => { @@ -824,7 +841,12 @@ impl ValueWrapper { } fn replace(&mut self, val: Value) { - self.val = val; + let is_null = match &val { + Value::Array(v) => if v.is_empty() { true } else { false }, + Value::Object(m) => if m.is_empty() { true } else { false }, + _ => val.is_null() + }; + self.val = if is_null { Value::Null } else { val }; } fn push(&mut self, v: Value) { @@ -1105,5 +1127,18 @@ mod tests { { "id" : 2, "name" : "Gray Berry" } ]); assert_eq!(&friends, jf.current_value()); + + // + // TODO 원본 json 순서여야 하나? + // + 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 jf = do_filter("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json"); + assert_eq!(&Value::Null, jf.current_value()); } } \ No newline at end of file