diff --git a/json-path/src/main/java/com/jayway/jsonpath/Configuration.java b/json-path/src/main/java/com/jayway/jsonpath/Configuration.java index dd59fd70..69427e1f 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/Configuration.java +++ b/json-path/src/main/java/com/jayway/jsonpath/Configuration.java @@ -254,4 +254,14 @@ public class Configuration { MappingProvider mappingProvider(); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Configuration that = (Configuration) o; + return jsonProvider.getClass() == that.jsonProvider.getClass() && + mappingProvider.getClass() == that.mappingProvider.getClass() && + Objects.equals(options, that.options); + } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/function/Parameter.java b/json-path/src/main/java/com/jayway/jsonpath/internal/function/Parameter.java index 0fe69a3a..b2c85c62 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/function/Parameter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/function/Parameter.java @@ -70,6 +70,10 @@ public class Parameter { this.json = json; } + public ILateBindingValue getILateBingValue(){ + return lateBinding; + } + /** * Translate the collection of parameters into a collection of values of type T. * diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/function/latebinding/PathLateBindingValue.java b/json-path/src/main/java/com/jayway/jsonpath/internal/function/latebinding/PathLateBindingValue.java index 2ece40ad..38139f3a 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/function/latebinding/PathLateBindingValue.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/function/latebinding/PathLateBindingValue.java @@ -17,6 +17,8 @@ package com.jayway.jsonpath.internal.function.latebinding; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.internal.Path; +import java.util.Objects; + /** * Defines the contract for late bindings, provides document state and enough context to perform the evaluation at a later * date such that we can operate on a dynamically changing value. @@ -26,21 +28,31 @@ import com.jayway.jsonpath.internal.Path; */ public class PathLateBindingValue implements ILateBindingValue { private final Path path; - private final Object rootDocument; + private final String rootDocument; private final Configuration configuration; - + private final Object result; public PathLateBindingValue(final Path path, final Object rootDocument, final Configuration configuration) { this.path = path; - this.rootDocument = rootDocument; + this.rootDocument = rootDocument.toString(); this.configuration = configuration; + this.result = path.evaluate(rootDocument, rootDocument, configuration).getValue(); } /** - * Evaluate the expression at the point of need for Path type expressions * * @return the late value */ public Object get() { - return path.evaluate(rootDocument, rootDocument, configuration).getValue(); + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PathLateBindingValue that = (PathLateBindingValue) o; + return Objects.equals(path, that.path) && + rootDocument.equals(that.rootDocument) && + Objects.equals(configuration, that.configuration); } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java index bc05bc5f..2d24b70d 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java @@ -48,17 +48,20 @@ public class FunctionPathToken extends PathToken { if (null != functionParams) { for (Parameter param : functionParams) { - if (!param.hasEvaluated()) { - switch (param.getType()) { - case PATH: - param.setLateBinding(new PathLateBindingValue(param.getPath(), ctx.rootDocument(), ctx.configuration())); + switch (param.getType()) { + case PATH: + PathLateBindingValue pathLateBindingValue = new PathLateBindingValue(param.getPath(), ctx.rootDocument(), ctx.configuration()); + if (!param.hasEvaluated()||!pathLateBindingValue.equals(param.getILateBingValue())) { + param.setLateBinding(pathLateBindingValue); param.setEvaluated(true); - break; - case JSON: + } + break; + case JSON: + if (!param.hasEvaluated()) { param.setLateBinding(new JsonLateBindingValue(ctx.configuration().jsonProvider(), param)); param.setEvaluated(true); - break; - } + } + break; } } } diff --git a/json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue680.java b/json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue680.java new file mode 100644 index 00000000..9a69a68b --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue680.java @@ -0,0 +1,47 @@ +package com.jayway.jsonpath.internal.function; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.spi.json.JsonSmartJsonProvider; +import com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class Issue680 { + + @Test + public void testIssue680concat() { + String json = "{ \"key\": \"first\"}"; + Object value = JsonPath.read(json, "concat(\"/\", $.key)"); + assertThat(value).isEqualTo("/first"); + json = "{ \"key\": \"second\"}"; + value = JsonPath.read(json, "concat(\"/\", $.key)"); + assertThat(value).isEqualTo("/second"); + } + + @Test + public void testIssue680min() { + String json = "{ \"key\": 1}"; + double value = JsonPath.read(json, "min($.key)"); + assertThat(value).isEqualTo(1d); + json = "{ \"key\": 2}"; + value = JsonPath.read(json, "min($.key)"); + assertThat(value).isEqualTo(2d); + } + + @Test + public void testIssue680concat_2() { + Map context = new HashMap(); + context.put("key", "first"); + Object value = JsonPath.read(context, "concat(\"/\", $.key)"); + assertThat(value).isEqualTo("/first"); + Map context2 = new HashMap(); + context2.put("key", "second"); + value = JsonPath.read(context2, "concat(\"/\", $.key)"); + assertThat(value).isEqualTo("/second"); + } +}