From fe8a2f70c09fd3a42e58012fa341ac0d1d24d9ba Mon Sep 17 00:00:00 2001 From: freestrings Date: Mon, 20 May 2019 12:20:00 +0900 Subject: [PATCH] The JSON comparison algorithm is changed --- src/filter/value_filter.rs | 6 ++--- src/filter/value_wrapper.rs | 53 ++++++++++++++++++++++++++----------- src/ref_value/model.rs | 26 +++++++++++++++--- tests/filter.rs | 23 ++++++++++++++-- 4 files changed, 85 insertions(+), 23 deletions(-) diff --git a/src/filter/value_filter.rs b/src/filter/value_filter.rs index 445de39..fb8c82b 100644 --- a/src/filter/value_filter.rs +++ b/src/filter/value_filter.rs @@ -232,14 +232,14 @@ impl ValueFilter { for v in vec { let nested_wrapper = get_nested_object(v, key, filter_mode); if !nested_wrapper.is_null() { - ret.push(nested_wrapper.clone()); + ret.push(nested_wrapper); } } buf.append(&mut ret); } else if v.is_object() { let nested_wrapper = get_nested_object(v, key, filter_mode); if !nested_wrapper.is_null() { - buf.push(nested_wrapper.clone()); + buf.push(nested_wrapper); } } else { match v.get(key.clone()) { @@ -256,7 +256,7 @@ impl ValueFilter { for v in vec { let wrapper = get_nested_object(v, key, filter_mode); if !wrapper.is_null() { - ret.push(wrapper.clone()); + ret.push(wrapper); } } RefValue::Array(ret).into() diff --git a/src/filter/value_wrapper.rs b/src/filter/value_wrapper.rs index fec9cd1..7782f8e 100644 --- a/src/filter/value_wrapper.rs +++ b/src/filter/value_wrapper.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use indexmap::IndexSet; +use indexmap::{IndexSet, IndexMap}; use serde_json::Value; use ref_value::model::*; @@ -87,6 +87,7 @@ impl ValueWrapper { set.insert(v.clone()); } } + let ret = set.into_iter().collect(); Some(ValueWrapper::new(RefValue::Array(ret).into(), false)) } @@ -155,22 +156,38 @@ impl ValueWrapper { self.val.is_array() } - fn into_hashset(&self) -> IndexSet { + fn into_hashset(&self) -> IndexSet<&RefValue> { trace!("into_hashset"); let mut hashset = IndexSet::new(); match self.val.deref() { RefValue::Array(ref v1) => { for v in v1 { - hashset.insert(v.clone()); + hashset.insert(v.deref()); } } _ => { - hashset.insert(self.val.clone()); + hashset.insert(self.val.deref()); } } hashset } + fn into_hashmap(&self) -> IndexMap<&RefValue, RefValueWrapper> { + trace!("into_hashmap"); + let mut hashmap = IndexMap::new(); + match self.val.deref() { + RefValue::Array(ref v1) => { + for v in v1 { + hashmap.insert(v.deref(), v.clone()); + } + } + _ => { + hashmap.insert(self.val.deref(), self.val.clone()); + } + } + hashmap + } + pub fn except(&self, other: &Self) -> Self { trace!("except"); let hashset = self.into_hashset(); @@ -178,13 +195,13 @@ impl ValueWrapper { match other.val.deref() { RefValue::Array(ref v1) => { for v in v1 { - if !hashset.contains(v) { + if !hashset.contains(v.deref()) { ret.insert(v.clone()); } } } _ => { - if !hashset.contains(&other.val) { + if !hashset.contains(&other.val.deref()) { ret.insert(other.val.clone()); } } @@ -201,13 +218,13 @@ impl ValueWrapper { match other.val.deref() { RefValue::Array(ref v1) => { for v in v1 { - if hashset.contains(v) { + if hashset.contains(v.deref()) { ret.insert(v.clone()); } } } - _ => { - if hashset.contains(&other.val) { + e => { + if hashset.contains(e) { ret.insert(other.val.clone()); } } @@ -219,24 +236,30 @@ impl ValueWrapper { pub fn union(&self, other: &Self) -> Self { trace!("union"); - let mut hashset = self.into_hashset(); + let origin = self.into_hashmap(); + let mut ret = IndexSet::new(); + + for o in origin.values() { + ret.insert(o.clone()); + } + match other.val.deref() { RefValue::Array(ref v1) => { for v in v1 { - if !hashset.contains(v) { - hashset.insert(v.clone()); + if !origin.contains_key(v.deref()) { + ret.insert(v.clone()); } } } _ => { - if !hashset.contains(&other.val) { - hashset.insert(other.val.clone()); + if !origin.contains_key(&other.val.deref()) { + ret.insert(other.val.clone()); } } } let mut vw = ValueWrapper::new(RefValue::Null.into(), false); - let list = hashset.into_iter().map(|val| val.clone()).collect(); + let list = ret.iter().map(|v| v.clone()).collect(); vw.replace(RefValue::Array(list).into()); vw } diff --git a/src/ref_value/model.rs b/src/ref_value/model.rs index bb259b2..694dd9d 100644 --- a/src/ref_value/model.rs +++ b/src/ref_value/model.rs @@ -5,14 +5,21 @@ use std::sync::Arc; use indexmap::map::IndexMap; use serde::ser::Serialize; use serde_json::{Number, Value}; +use std::collections::hash_map::DefaultHasher; type TypeRefValue = Arc>; -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub struct RefValueWrapper { data: TypeRefValue } +impl PartialEq for RefValueWrapper { + fn eq(&self, other: &RefValueWrapper) -> bool { + Arc::ptr_eq(&self.data, &other.data) + } +} + impl Eq for RefValueWrapper {} impl Deref for RefValueWrapper { @@ -113,7 +120,7 @@ impl RefIndex for String { } } -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub enum RefValue { Null, Bool(bool), @@ -123,6 +130,18 @@ pub enum RefValue { Object(IndexMap), } +impl PartialEq for RefValue { + fn eq(&self, other: &RefValue) -> bool { + let mut hasher1 = DefaultHasher::new(); + let mut hasher2 = DefaultHasher::new(); + + self.hash(&mut hasher1); + other.hash(&mut hasher2); + + hasher1.finish() == hasher2.finish() + } +} + static REF_VALUE_NULL: &'static str = "$jsonpath::ref_value::model::RefValue::Null"; impl Hash for RefValue { @@ -147,7 +166,8 @@ impl Hash for RefValue { s.hash(state) } RefValue::Object(map) => { - for (_, v) in map { + for (k, v) in map { + k.hash(state); v.hash(state); } } diff --git a/tests/filter.rs b/tests/filter.rs index 267b7a3..1007ed4 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -1,3 +1,4 @@ +extern crate core; extern crate env_logger; extern crate jsonpath_lib as jsonpath; #[macro_use] @@ -6,7 +7,8 @@ extern crate serde_json; use std::io::Read; use serde_json::Value; -use jsonpath::filter::value_filter::{ValueFilter, JsonValueFilter}; + +use jsonpath::filter::value_filter::{JsonValueFilter, ValueFilter}; use jsonpath::parser::parser::Parser; fn setup() { @@ -230,7 +232,6 @@ fn op_default() { parser.parse(&mut jf).unwrap(); let friends = json!([{ "name" : "친구3", "age" : 30 }]); assert_eq!(friends, jf.into_value()); - } #[test] @@ -308,6 +309,7 @@ fn op_complex() { let ret = jsonpath::select(&json, r#"$.[?(@.a > "1")]"#).unwrap(); assert_eq!(Value::Null, ret); } + #[test] fn example() { setup(); @@ -448,4 +450,21 @@ fn example() { let jf = do_filter("$..*", "./benches/example.json"); let json: Value = serde_json::from_str(read_json("./benches/giveme_every_thing_result.json").as_str()).unwrap(); assert_eq!(json, jf.into_value()); +} + +#[test] +fn filer_same_obj() { + setup(); + + let mut jf = JsonValueFilter::new(r#" + { + "a": 1, + "b" : {"a": 1}, + "c" : {"a": 1} + } + "#).unwrap(); + let mut parser = Parser::new("$..[?(@.a == 1)]"); + parser.parse(&mut jf).unwrap(); + let ret = jf.into_value(); + println!("{:?}", ret); } \ No newline at end of file