Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue394: get parent node by child node #713

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fix Issue394: get parent node by child node
  • Loading branch information
zengmmm00 committed May 20, 2021
commit a437543e1a6493e9c1ed539bca7533288637272d
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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.
Expand Down Expand Up @@ -626,7 +627,11 @@ public ValueNode evaluate(Predicate.PredicateContext ctx) {
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ public EvaluationContext evaluate(Object document, Object rootDocument, Configur
}

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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -39,6 +40,14 @@ public PredicateContextImpl(Object contextDocument, Object rootDocument, Configu
this.documentPathCache = documentPathCache;
}

public boolean isExtractingParentNode(){
return isExtractingParentNode;
}

public void setExtractingParentNode(){
this.isExtractingParentNode = true;
}

public Object evaluate(Path path){
Object result;
if(path.isRootPath()){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ public void evaluate(String currentPath, PathRef ref, Object model, EvaluationCo

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)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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 changes: 75 additions & 0 deletions json-path/src/test/resources/issue_394.json
Original file line number Diff line number Diff line change
@@ -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
}
}