From 5174797534b5983733c7a43b6bf1af0ddb55732d Mon Sep 17 00:00:00 2001 From: skwqy Date: Mon, 12 Sep 2022 09:42:42 +0800 Subject: [PATCH 1/3] Fix #857 DCollecting all values for given key in object array returns empty Collection --- .../jsonpath/internal/path/PathToken.java | 49 ++++++++++--------- .../java/com/jayway/jsonpath/Issue_857.java | 28 +++++++++++ 2 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 json-path/src/test/java/com/jayway/jsonpath/Issue_857.java diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java index 34cf1402..83141c75 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java @@ -32,7 +32,7 @@ public abstract class PathToken { private int upstreamArrayIndex = -1; - public void setUpstreamArrayIndex(int idx){ + public void setUpstreamArrayIndex(int idx) { upstreamArrayIndex = idx; } @@ -44,32 +44,32 @@ public abstract class PathToken { void handleObjectProperty(String currentPath, Object model, EvaluationContextImpl ctx, List properties) { - if(properties.size() == 1) { + if (properties.size() == 1) { String property = properties.get(0); String evalPath = Utils.concat(currentPath, "['", property, "']"); Object propertyVal = readObjectProperty(property, model, ctx); - if(propertyVal == JsonProvider.UNDEFINED){ + if (propertyVal == JsonProvider.UNDEFINED) { // Conditions below heavily depend on current token type (and its logic) and are not "universal", // so this code is quite dangerous (I'd rather rewrite it & move to PropertyPathToken and implemented // WildcardPathToken as a dynamic multi prop case of PropertyPathToken). // Better safe than sorry. assert this instanceof PropertyPathToken : "only PropertyPathToken is supported"; - if(isLeaf()) { - if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){ - propertyVal = null; + if (isLeaf()) { + if (ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { + propertyVal = null; } else { - if(ctx.options().contains(Option.SUPPRESS_EXCEPTIONS) || - !ctx.options().contains(Option.REQUIRE_PROPERTIES)){ + if (ctx.options().contains(Option.SUPPRESS_EXCEPTIONS) || + !ctx.options().contains(Option.REQUIRE_PROPERTIES)) { return; } else { throw new PathNotFoundException("No results for path: " + evalPath); } } } else { - if (! (isUpstreamDefinite() && isTokenDefinite()) && - !ctx.options().contains(Option.REQUIRE_PROPERTIES) || - ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){ + if (!(isUpstreamDefinite() && isTokenDefinite()) && + !ctx.options().contains(Option.REQUIRE_PROPERTIES) || + ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) { // If there is some indefiniteness in the path and properties are not required - we'll ignore // absent property. And also in case of exception suppression - so that other path evaluation // branches could be examined. @@ -82,11 +82,11 @@ public abstract class PathToken { PathRef pathRef = ctx.forUpdate() ? PathRef.create(model, property) : PathRef.NO_OP; if (isLeaf()) { String idx = "[" + String.valueOf(upstreamArrayIndex) + "]"; - if(idx.equals("[-1]") || ctx.getRoot().getTail().prev().getPathFragment().equals(idx)){ + if (idx.equals("[-1]") || ctx.getRoot().getTail().prev().getPathFragment().equals(idx) || + ctx.getRoot().getTail().prev().getPathFragment().equals("[*]")) { ctx.addResult(evalPath, pathRef, propertyVal); } - } - else { + } else { next().evaluate(evalPath, pathRef, propertyVal, ctx); } } else { @@ -97,17 +97,17 @@ public abstract class PathToken { Object merged = ctx.jsonProvider().createMap(); for (String property : properties) { Object propertyVal; - if(hasProperty(property, model, ctx)) { + if (hasProperty(property, model, ctx)) { propertyVal = readObjectProperty(property, model, ctx); - if(propertyVal == JsonProvider.UNDEFINED){ - if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { + if (propertyVal == JsonProvider.UNDEFINED) { + if (ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { propertyVal = null; } else { continue; } } } else { - if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){ + if (ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { propertyVal = null; } else if (ctx.options().contains(Option.REQUIRE_PROPERTIES)) { throw new PathNotFoundException("Missing property in path " + evalPath); @@ -146,7 +146,7 @@ public abstract class PathToken { } } - PathToken prev(){ + PathToken prev() { return prev; } @@ -162,7 +162,7 @@ public abstract class PathToken { } boolean isRoot() { - return prev == null; + return prev == null; } boolean isUpstreamDefinite() { @@ -176,7 +176,7 @@ public abstract class PathToken { int cnt = 1; PathToken token = this; - while (!token.isLeaf()){ + while (!token.isLeaf()) { token = token.next(); cnt++; } @@ -184,7 +184,7 @@ public abstract class PathToken { } public boolean isPathDefinite() { - if(definite != null){ + if (definite != null) { return definite.booleanValue(); } boolean isDefinite = isTokenDefinite(); @@ -214,11 +214,12 @@ public abstract class PathToken { return super.equals(obj); } - public void invoke(PathFunction pathFunction, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) { + public void invoke(PathFunction pathFunction, String currentPath, PathRef parent, Object model, + EvaluationContextImpl ctx) { ctx.addResult(currentPath, parent, pathFunction.invoke(currentPath, parent, model, ctx, null)); } - public abstract void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx); + public abstract void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx); public abstract boolean isTokenDefinite(); diff --git a/json-path/src/test/java/com/jayway/jsonpath/Issue_857.java b/json-path/src/test/java/com/jayway/jsonpath/Issue_857.java new file mode 100644 index 00000000..6b4ddab9 --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/Issue_857.java @@ -0,0 +1,28 @@ +package com.jayway.jsonpath; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author skwqyg + * @Created on 2022 09 2022/9/10 16:36 + */ +public class Issue_857 extends BaseTest{ + + @Test + public void test(){ + Collection values = JsonPath.parse("[{\"key\":\"first value\"},{\"key\":\"second value\"}]") + .read("$..[*].key", java.util.Collection.class); + Assert.assertEquals(2,values.size()); + Set expect = new HashSet<>(); + expect.add("first value"); + expect.add("second value"); + Assert.assertTrue(expect.containsAll(values)); + System.out.println(values); + } + +} From bbd2bda83251c82d1f6c3a8c161991afccec476c Mon Sep 17 00:00:00 2001 From: skwqy Date: Mon, 12 Sep 2022 17:39:02 +0800 Subject: [PATCH 2/3] Fix #857 DCollecting all values for given key in object array returns empty Collection --- .../jsonpath/internal/path/PathToken.java | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java index 83141c75..ae19a632 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java @@ -32,7 +32,7 @@ public abstract class PathToken { private int upstreamArrayIndex = -1; - public void setUpstreamArrayIndex(int idx) { + public void setUpstreamArrayIndex(int idx){ upstreamArrayIndex = idx; } @@ -44,32 +44,32 @@ public abstract class PathToken { void handleObjectProperty(String currentPath, Object model, EvaluationContextImpl ctx, List properties) { - if (properties.size() == 1) { + if(properties.size() == 1) { String property = properties.get(0); String evalPath = Utils.concat(currentPath, "['", property, "']"); Object propertyVal = readObjectProperty(property, model, ctx); - if (propertyVal == JsonProvider.UNDEFINED) { + if(propertyVal == JsonProvider.UNDEFINED){ // Conditions below heavily depend on current token type (and its logic) and are not "universal", // so this code is quite dangerous (I'd rather rewrite it & move to PropertyPathToken and implemented // WildcardPathToken as a dynamic multi prop case of PropertyPathToken). // Better safe than sorry. assert this instanceof PropertyPathToken : "only PropertyPathToken is supported"; - if (isLeaf()) { - if (ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { - propertyVal = null; + if(isLeaf()) { + if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){ + propertyVal = null; } else { - if (ctx.options().contains(Option.SUPPRESS_EXCEPTIONS) || - !ctx.options().contains(Option.REQUIRE_PROPERTIES)) { + if(ctx.options().contains(Option.SUPPRESS_EXCEPTIONS) || + !ctx.options().contains(Option.REQUIRE_PROPERTIES)){ return; } else { throw new PathNotFoundException("No results for path: " + evalPath); } } } else { - if (!(isUpstreamDefinite() && isTokenDefinite()) && + if (! (isUpstreamDefinite() && isTokenDefinite()) && !ctx.options().contains(Option.REQUIRE_PROPERTIES) || - ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) { + ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){ // If there is some indefiniteness in the path and properties are not required - we'll ignore // absent property. And also in case of exception suppression - so that other path evaluation // branches could be examined. @@ -82,11 +82,12 @@ public abstract class PathToken { PathRef pathRef = ctx.forUpdate() ? PathRef.create(model, property) : PathRef.NO_OP; if (isLeaf()) { String idx = "[" + String.valueOf(upstreamArrayIndex) + "]"; - if (idx.equals("[-1]") || ctx.getRoot().getTail().prev().getPathFragment().equals(idx) || - ctx.getRoot().getTail().prev().getPathFragment().equals("[*]")) { + if(idx.equals("[-1]") || ctx.getRoot().getTail().prev().getPathFragment().equals(idx) || + ctx.getRoot().getTail().prev().getPathFragment().equals("[*]")){ ctx.addResult(evalPath, pathRef, propertyVal); } - } else { + } + else { next().evaluate(evalPath, pathRef, propertyVal, ctx); } } else { @@ -97,17 +98,17 @@ public abstract class PathToken { Object merged = ctx.jsonProvider().createMap(); for (String property : properties) { Object propertyVal; - if (hasProperty(property, model, ctx)) { + if(hasProperty(property, model, ctx)) { propertyVal = readObjectProperty(property, model, ctx); - if (propertyVal == JsonProvider.UNDEFINED) { - if (ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { + if(propertyVal == JsonProvider.UNDEFINED){ + if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { propertyVal = null; } else { continue; } } } else { - if (ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) { + if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){ propertyVal = null; } else if (ctx.options().contains(Option.REQUIRE_PROPERTIES)) { throw new PathNotFoundException("Missing property in path " + evalPath); @@ -146,7 +147,7 @@ public abstract class PathToken { } } - PathToken prev() { + PathToken prev(){ return prev; } @@ -162,7 +163,7 @@ public abstract class PathToken { } boolean isRoot() { - return prev == null; + return prev == null; } boolean isUpstreamDefinite() { @@ -176,7 +177,7 @@ public abstract class PathToken { int cnt = 1; PathToken token = this; - while (!token.isLeaf()) { + while (!token.isLeaf()){ token = token.next(); cnt++; } @@ -184,7 +185,7 @@ public abstract class PathToken { } public boolean isPathDefinite() { - if (definite != null) { + if(definite != null){ return definite.booleanValue(); } boolean isDefinite = isTokenDefinite(); @@ -214,12 +215,11 @@ public abstract class PathToken { return super.equals(obj); } - public void invoke(PathFunction pathFunction, String currentPath, PathRef parent, Object model, - EvaluationContextImpl ctx) { + public void invoke(PathFunction pathFunction, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) { ctx.addResult(currentPath, parent, pathFunction.invoke(currentPath, parent, model, ctx, null)); } - public abstract void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx); + public abstract void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx); public abstract boolean isTokenDefinite(); From c29ab1a7bb3ec712a49fc145218b18fa242aa806 Mon Sep 17 00:00:00 2001 From: skwqy Date: Mon, 12 Sep 2022 18:03:08 +0800 Subject: [PATCH 3/3] Fix #857 Collecting all values for given key in object array returns empty Collection --- .../java/com/jayway/jsonpath/internal/path/PathToken.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java index ae19a632..150c27c8 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java @@ -60,7 +60,7 @@ public abstract class PathToken { propertyVal = null; } else { if(ctx.options().contains(Option.SUPPRESS_EXCEPTIONS) || - !ctx.options().contains(Option.REQUIRE_PROPERTIES)){ + !ctx.options().contains(Option.REQUIRE_PROPERTIES)){ return; } else { throw new PathNotFoundException("No results for path: " + evalPath); @@ -68,8 +68,8 @@ public abstract class PathToken { } } else { if (! (isUpstreamDefinite() && isTokenDefinite()) && - !ctx.options().contains(Option.REQUIRE_PROPERTIES) || - ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){ + !ctx.options().contains(Option.REQUIRE_PROPERTIES) || + ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){ // If there is some indefiniteness in the path and properties are not required - we'll ignore // absent property. And also in case of exception suppression - so that other path evaluation // branches could be examined.