Improve filtering on objects (argument matching nested object)
Closed this issue ยท 6 comments
This is related to comparison test case https://cburgmer.github.io/json-path-comparison/results/filter_expression_after_recursive_descent.html#Java_com.github.jsurfer
Consider the following JSON:
[
{"letter" : "A", "number": 1, "boolean": true},
{"letter" : "B", "number": 2, "boolean": false, "next": {"letter" : "X", "number": 1.1, "boolean": true } },
{"letter" : "C", "number": 3, "boolean": true, "next": {"letter" : "X", "number": 1.2, "boolean": false } },
{"letter" : "D", "number": 4, "boolean": true, "next": {"letter" : "X", "number": 1.3, "boolean": true } }
]
and the following Java snippet:
String expression = // The JsonPath expression
InputStream is = getClass().getClassLoader().getResourceAsStream("MultiJsonPath.json");
JsonSurfer surfer = new JsonSurfer(JacksonParser.INSTANCE, JacksonProvider.INSTANCE);
Collector collector = surfer.collector(is);
ValueBox<Collection<Object>> matches = collector.collectAll(expression);
collector.exec();
Iterator<Object> iter = matches.get().iterator();
while(iter.hasNext()){
Object o = iter.next();
System.err.println(o.getClass());
if(o instanceof Map) {
Iterator<Entry> iten = ((Map) o).entrySet().iterator();
while (iten.hasNext()) {
System.err.println(" > " + iten.next());
}
}
}
I get the following behaviour with the path expressions
Expression: $..[?(@.letter == 'X')]
(does not work as expected)
class java.util.LinkedHashMap
> letter=B
> number=2
> boolean=false
> next={letter=X, number=1.1, boolean=true}
class java.util.LinkedHashMap
> letter=C
> number=3
> boolean=true
> next={letter=X, number=1.2, boolean=false}
class java.util.LinkedHashMap
> letter=D
> number=4
> boolean=true
> next={letter=X, number=1.3, boolean=true}
I would have expected instead, matches of the inner JsonObjects only:
class java.util.LinkedHashMap
> letter=X
> number=1.1
> boolean=true
class java.util.LinkedHashMap
> letter=X
> number=1.2
> boolean=false
class java.util.LinkedHashMap
> letter=X
> number=1.3
> boolean=true
Changing the expression to matching one object in the first 'layer' works as expected.
Expression $..[?(@.letter == 'A')]
(works as expected)
class java.util.LinkedHashMap
> letter=A
> number=1
> boolean=true
Expression $..[?(@.number == 1.2)]
(does not work as expected)
class java.util.LinkedHashMap
> letter=C
> number=3
> boolean=true
> next={letter=X, number=1.2, boolean=false}
I think the problem is indeed the fact that the match is including the containing object, but it should not (at least, from my understanding of JsonPath). The behaviour I would have expected is the one of Jayway, I tried with https://jsonpath.herokuapp.com . However, I want to stick to JsonSurfer for the streaming capabilities.
For reference, the case is implemented as a test here and relates to this feature issue
Thanks so much for reporting. I'll examine the code to see if any quick fix on this.
@enridaga the first working implementation just submitted. Please feel free to pull the source and test
Works as expected now -- we may do more tests later but in the meantime this looks very good -- look forward to the release!
Any plan for the next release?
Any plan for the next release?
Merged in master
published