Browse Source

Fix Issue394: get parent node by child node

pull/713/head
zengmmm00 4 years ago
parent
commit
a437543e1a
  1. 7
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java
  2. 5
      json-path/src/main/java/com/jayway/jsonpath/internal/path/CompiledPath.java
  3. 9
      json-path/src/main/java/com/jayway/jsonpath/internal/path/EvaluationContextImpl.java
  4. 9
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicateContextImpl.java
  5. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicatePathToken.java
  6. 38
      json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue394.java
  7. 75
      json-path/src/test/resources/issue_394.json

7
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java

@ -23,6 +23,7 @@ import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.minidev.json.JSONArray;
/**
* Moved these nodes out of the ValueNode abstract class.
@ -626,7 +627,11 @@ public interface ValueNodes {
try {
Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build();
Object result = path.evaluate(ctx.item(), ctx.root(), c).getValue(false);
return result == JsonProvider.UNDEFINED ? FALSE : TRUE;
if (((PredicateContextImpl)ctx).isExtractingParentNode() && result instanceof JSONArray) {
return (result == JsonProvider.UNDEFINED) || (((JSONArray) result).size() == 0) ? FALSE : TRUE;
} else {
return result == JsonProvider.UNDEFINED ? FALSE : TRUE;
}
} catch (PathNotFoundException e) {
return FALSE;
}

5
json-path/src/main/java/com/jayway/jsonpath/internal/path/CompiledPath.java

@ -94,6 +94,11 @@ public class CompiledPath implements Path {
}
EvaluationContextImpl ctx = new EvaluationContextImpl(this, rootDocument, configuration, forUpdate);
if (document == rootDocument){
ctx.setRoot();
}
try {
PathRef op = ctx.forUpdate() ? PathRef.createRoot(rootDocument) : PathRef.NO_OP;
root.evaluate("", op, document, ctx);

9
json-path/src/main/java/com/jayway/jsonpath/internal/path/EvaluationContextImpl.java

@ -49,8 +49,17 @@ public class EvaluationContextImpl implements EvaluationContext {
private final HashMap<Path, Object> documentEvalCache = new HashMap<Path, Object>();
private final boolean forUpdate;
private int resultIndex = 0;
private boolean root = false;
public boolean isRoot() {
return root;
}
public void setRoot() {
root = true;
}
public EvaluationContextImpl(Path path, Object rootDocument, Configuration configuration, boolean forUpdate) {
notNull(path, "path can not be null");
notNull(rootDocument, "root can not be null");

9
json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicateContextImpl.java

@ -31,6 +31,7 @@ public class PredicateContextImpl implements Predicate.PredicateContext {
private final Object rootDocument;
private final Configuration configuration;
private final HashMap<Path, Object> documentPathCache;
private boolean isExtractingParentNode = false;
public PredicateContextImpl(Object contextDocument, Object rootDocument, Configuration configuration, HashMap<Path, Object> documentPathCache) {
this.contextDocument = contextDocument;
@ -39,6 +40,14 @@ public class PredicateContextImpl implements Predicate.PredicateContext {
this.documentPathCache = documentPathCache;
}
public boolean isExtractingParentNode(){
return isExtractingParentNode;
}
public void setExtractingParentNode(){
this.isExtractingParentNode = true;
}
public Object evaluate(Path path){
Object result;
if(path.isRootPath()){

4
json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicatePathToken.java

@ -71,7 +71,9 @@ public class PredicatePathToken extends PathToken {
public boolean accept(final Object obj, final Object root, final Configuration configuration, EvaluationContextImpl evaluationContext) {
Predicate.PredicateContext ctx = new PredicateContextImpl(obj, root, configuration, evaluationContext.documentEvalCache());
if (evaluationContext.isRoot()){
((PredicateContextImpl) ctx).setExtractingParentNode();
}
for (Predicate predicate : predicates) {
try {
if (!predicate.apply(ctx)) {

38
json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue394.java

@ -0,0 +1,38 @@
package com.jayway.jsonpath.internal.function;
import net.minidev.json.JSONArray;
import com.jayway.jsonpath.JsonPath;
import org.junit.Test;
import java.io.InputStream;
import java.util.LinkedHashMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class Issue394 {
@Test
public void testGetParentNodeByChildNodeFromStream(){
InputStream stream = ClassLoader.getSystemResourceAsStream("issue_394.json");
JSONArray arr = JsonPath.parse(stream).read("$.street.store.book[?(@.authors[?(@.lastName == 'Waugh')])]");
assertEquals(arr.size(),1);
}
@Test
public void testGetParentNodeByChildNodeFromJson(){
String json = "{\n" +
" \"parent\": {\n" +
" \"children\": [\n{\n" +
" \"index\": \"0\",\n" +
" \"name\": \"A\"\n},\n{\n" +
" \"index\": \"1\",\n" +
" \"name\": \"B\"\n},\n{\n" +
" \"index\": \"2\",\n" +
" \"name\": \"C\"\n}\n]\n}\n}";
JSONArray arr = JsonPath.read(json,"$.parent[?(@.children[?(@.index == '2')])]");
assertNotNull(((LinkedHashMap) arr.get(0)).get("children"));
}
}

75
json-path/src/test/resources/issue_394.json

@ -0,0 +1,75 @@
{
"street": {
"store": {
"book": [
{
"category": "reference",
"authors": [
{
"firstName": "Nigel",
"lastName": "Rees"
},
{
"firstName": "Evelyn",
"lastName": "Waugh"
}
],
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"authors": [
{
"firstName": "A",
"lastName": "B"
},
{
"firstName": "C",
"lastName": "D"
}
],
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"authors": [
{
"firstName": "A",
"lastName": "D"
},
{
"firstName": "Evelyn",
"lastName": "X"
}
],
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"authors": [
{
"firstName": "Nigel",
"lastName": "Rees"
},
{
"firstName": "Evelyn",
"lastName": "X"
}
],
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
}
Loading…
Cancel
Save