mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-05-05 06:02:13 +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 {
|
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()
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user