The JSON comparison algorithm is changed

This commit is contained in:
freestrings 2019-05-20 12:20:00 +09:00
parent 846ad26e2c
commit fe8a2f70c0
4 changed files with 85 additions and 23 deletions

View File

@ -232,14 +232,14 @@ impl ValueFilter {
for v in vec { for v in vec {
let nested_wrapper = get_nested_object(v, key, filter_mode); let nested_wrapper = get_nested_object(v, key, filter_mode);
if !nested_wrapper.is_null() { if !nested_wrapper.is_null() {
ret.push(nested_wrapper.clone()); ret.push(nested_wrapper);
} }
} }
buf.append(&mut ret); buf.append(&mut ret);
} else if v.is_object() { } else if v.is_object() {
let nested_wrapper = get_nested_object(v, key, filter_mode); let nested_wrapper = get_nested_object(v, key, filter_mode);
if !nested_wrapper.is_null() { if !nested_wrapper.is_null() {
buf.push(nested_wrapper.clone()); buf.push(nested_wrapper);
} }
} else { } else {
match v.get(key.clone()) { match v.get(key.clone()) {
@ -256,7 +256,7 @@ impl ValueFilter {
for v in vec { for v in vec {
let wrapper = get_nested_object(v, key, filter_mode); let wrapper = get_nested_object(v, key, filter_mode);
if !wrapper.is_null() { if !wrapper.is_null() {
ret.push(wrapper.clone()); ret.push(wrapper);
} }
} }
RefValue::Array(ret).into() RefValue::Array(ret).into()

View File

@ -1,6 +1,6 @@
use std::ops::Deref; use std::ops::Deref;
use indexmap::IndexSet; use indexmap::{IndexSet, IndexMap};
use serde_json::Value; use serde_json::Value;
use ref_value::model::*; use ref_value::model::*;
@ -87,6 +87,7 @@ impl ValueWrapper {
set.insert(v.clone()); set.insert(v.clone());
} }
} }
let ret = set.into_iter().collect(); let ret = set.into_iter().collect();
Some(ValueWrapper::new(RefValue::Array(ret).into(), false)) Some(ValueWrapper::new(RefValue::Array(ret).into(), false))
} }
@ -155,22 +156,38 @@ impl ValueWrapper {
self.val.is_array() self.val.is_array()
} }
fn into_hashset(&self) -> IndexSet<RefValueWrapper> { fn into_hashset(&self) -> IndexSet<&RefValue> {
trace!("into_hashset"); trace!("into_hashset");
let mut hashset = IndexSet::new(); let mut hashset = IndexSet::new();
match self.val.deref() { match self.val.deref() {
RefValue::Array(ref v1) => { RefValue::Array(ref v1) => {
for v in v1 { for v in v1 {
hashset.insert(v.clone()); hashset.insert(v.deref());
} }
} }
_ => { _ => {
hashset.insert(self.val.clone()); hashset.insert(self.val.deref());
} }
} }
hashset 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 { pub fn except(&self, other: &Self) -> Self {
trace!("except"); trace!("except");
let hashset = self.into_hashset(); let hashset = self.into_hashset();
@ -178,13 +195,13 @@ impl ValueWrapper {
match other.val.deref() { match other.val.deref() {
RefValue::Array(ref v1) => { RefValue::Array(ref v1) => {
for v in v1 { for v in v1 {
if !hashset.contains(v) { if !hashset.contains(v.deref()) {
ret.insert(v.clone()); ret.insert(v.clone());
} }
} }
} }
_ => { _ => {
if !hashset.contains(&other.val) { if !hashset.contains(&other.val.deref()) {
ret.insert(other.val.clone()); ret.insert(other.val.clone());
} }
} }
@ -201,13 +218,13 @@ impl ValueWrapper {
match other.val.deref() { match other.val.deref() {
RefValue::Array(ref v1) => { RefValue::Array(ref v1) => {
for v in v1 { for v in v1 {
if hashset.contains(v) { if hashset.contains(v.deref()) {
ret.insert(v.clone()); ret.insert(v.clone());
} }
} }
} }
_ => { e => {
if hashset.contains(&other.val) { if hashset.contains(e) {
ret.insert(other.val.clone()); ret.insert(other.val.clone());
} }
} }
@ -219,24 +236,30 @@ impl ValueWrapper {
pub fn union(&self, other: &Self) -> Self { pub fn union(&self, other: &Self) -> Self {
trace!("union"); 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() { match other.val.deref() {
RefValue::Array(ref v1) => { RefValue::Array(ref v1) => {
for v in v1 { for v in v1 {
if !hashset.contains(v) { if !origin.contains_key(v.deref()) {
hashset.insert(v.clone()); ret.insert(v.clone());
} }
} }
} }
_ => { _ => {
if !hashset.contains(&other.val) { if !origin.contains_key(&other.val.deref()) {
hashset.insert(other.val.clone()); ret.insert(other.val.clone());
} }
} }
} }
let mut vw = ValueWrapper::new(RefValue::Null.into(), false); 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.replace(RefValue::Array(list).into());
vw vw
} }

View File

@ -5,14 +5,21 @@ use std::sync::Arc;
use indexmap::map::IndexMap; use indexmap::map::IndexMap;
use serde::ser::Serialize; use serde::ser::Serialize;
use serde_json::{Number, Value}; use serde_json::{Number, Value};
use std::collections::hash_map::DefaultHasher;
type TypeRefValue = Arc<Box<RefValue>>; type TypeRefValue = Arc<Box<RefValue>>;
#[derive(Debug, PartialEq)] #[derive(Debug)]
pub struct RefValueWrapper { pub struct RefValueWrapper {
data: TypeRefValue data: TypeRefValue
} }
impl PartialEq for RefValueWrapper {
fn eq(&self, other: &RefValueWrapper) -> bool {
Arc::ptr_eq(&self.data, &other.data)
}
}
impl Eq for RefValueWrapper {} impl Eq for RefValueWrapper {}
impl Deref for RefValueWrapper { impl Deref for RefValueWrapper {
@ -113,7 +120,7 @@ impl RefIndex for String {
} }
} }
#[derive(Debug, PartialEq)] #[derive(Debug)]
pub enum RefValue { pub enum RefValue {
Null, Null,
Bool(bool), Bool(bool),
@ -123,6 +130,18 @@ pub enum RefValue {
Object(IndexMap<String, RefValueWrapper>), Object(IndexMap<String, RefValueWrapper>),
} }
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"; static REF_VALUE_NULL: &'static str = "$jsonpath::ref_value::model::RefValue::Null";
impl Hash for RefValue { impl Hash for RefValue {
@ -147,7 +166,8 @@ impl Hash for RefValue {
s.hash(state) s.hash(state)
} }
RefValue::Object(map) => { RefValue::Object(map) => {
for (_, v) in map { for (k, v) in map {
k.hash(state);
v.hash(state); v.hash(state);
} }
} }

View File

@ -1,3 +1,4 @@
extern crate core;
extern crate env_logger; extern crate env_logger;
extern crate jsonpath_lib as jsonpath; extern crate jsonpath_lib as jsonpath;
#[macro_use] #[macro_use]
@ -6,7 +7,8 @@ extern crate serde_json;
use std::io::Read; use std::io::Read;
use serde_json::Value; use serde_json::Value;
use jsonpath::filter::value_filter::{ValueFilter, JsonValueFilter};
use jsonpath::filter::value_filter::{JsonValueFilter, ValueFilter};
use jsonpath::parser::parser::Parser; use jsonpath::parser::parser::Parser;
fn setup() { fn setup() {
@ -230,7 +232,6 @@ fn op_default() {
parser.parse(&mut jf).unwrap(); parser.parse(&mut jf).unwrap();
let friends = json!([{ "name" : "친구3", "age" : 30 }]); let friends = json!([{ "name" : "친구3", "age" : 30 }]);
assert_eq!(friends, jf.into_value()); assert_eq!(friends, jf.into_value());
} }
#[test] #[test]
@ -308,6 +309,7 @@ fn op_complex() {
let ret = jsonpath::select(&json, r#"$.[?(@.a > "1")]"#).unwrap(); let ret = jsonpath::select(&json, r#"$.[?(@.a > "1")]"#).unwrap();
assert_eq!(Value::Null, ret); assert_eq!(Value::Null, ret);
} }
#[test] #[test]
fn example() { fn example() {
setup(); setup();
@ -449,3 +451,20 @@ fn example() {
let json: Value = serde_json::from_str(read_json("./benches/giveme_every_thing_result.json").as_str()).unwrap(); let json: Value = serde_json::from_str(read_json("./benches/giveme_every_thing_result.json").as_str()).unwrap();
assert_eq!(json, jf.into_value()); 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);
}