mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-05-01 20:22:16 +00:00
The JSON comparison algorithm is changed
This commit is contained in:
parent
846ad26e2c
commit
fe8a2f70c0
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user