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 {
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()

View File

@ -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<RefValueWrapper> {
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
}

View File

@ -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<Box<RefValue>>;
#[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<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";
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);
}
}

View File

@ -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);
}