diff --git a/json-unit-json-path/src/main/java/net/javacrumbs/jsonunit/jsonpath/JsonPathAdapter.java b/json-unit-json-path/src/main/java/net/javacrumbs/jsonunit/jsonpath/JsonPathAdapter.java index 73257db2..fdc7fac3 100644 --- a/json-unit-json-path/src/main/java/net/javacrumbs/jsonunit/jsonpath/JsonPathAdapter.java +++ b/json-unit-json-path/src/main/java/net/javacrumbs/jsonunit/jsonpath/JsonPathAdapter.java @@ -16,6 +16,7 @@ package net.javacrumbs.jsonunit.jsonpath; import static com.jayway.jsonpath.Configuration.defaultConfiguration; +import static net.javacrumbs.jsonunit.core.internal.JsonUtils.getPathPrefix; import static net.javacrumbs.jsonunit.core.internal.JsonUtils.jsonSource; import static net.javacrumbs.jsonunit.core.internal.JsonUtils.missingNode; import static net.javacrumbs.jsonunit.core.internal.JsonUtils.wrapDeserializedObject; @@ -37,13 +38,25 @@ private JsonPathAdapter() {} @NotNull public static Object inPath(@Nullable Object json, @NotNull String path) { - String normalizedPath = fromBracketNotation(path); try { MatchRecordingListener recordingListener = new MatchRecordingListener(); Object value = readValue(defaultConfiguration().addEvaluationListeners(recordingListener), json, path); - return jsonSource(wrapDeserializedObject(value), normalizedPath, recordingListener.getMatchingPaths()); + return jsonSource(wrapDeserializedObject(value), concatJsonPaths(json, path), recordingListener.getMatchingPaths()); } catch (PathNotFoundException e) { - return jsonSource(missingNode(), normalizedPath); + return jsonSource(missingNode(), concatJsonPaths(json, path)); + } + } + + private static @NotNull String concatJsonPaths(@Nullable Object json, @NotNull String path) { + String newPathSegment = fromBracketNotation(path); + String pathPrefix = getPathPrefix(json); + if (pathPrefix.isEmpty()) { + return newPathSegment; + } + if (newPathSegment.startsWith("$.")) { + return pathPrefix + newPathSegment.substring(1); + } else { + return pathPrefix + newPathSegment; } } diff --git a/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatcher.java b/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatcher.java index ae7e1f6f..259e991b 100644 --- a/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatcher.java +++ b/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatcher.java @@ -18,10 +18,13 @@ import java.util.function.Consumer; import java.util.function.Function; import net.javacrumbs.jsonunit.core.Configuration; +import net.javacrumbs.jsonunit.core.internal.JsonUtils; import net.javacrumbs.jsonunit.core.internal.Path; import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher; import org.jetbrains.annotations.NotNull; +import static net.javacrumbs.jsonunit.core.internal.JsonUtils.getPathPrefix; + abstract class AbstractSpringMatcher { private final Path path; private final Configuration configuration; @@ -40,6 +43,8 @@ abstract class AbstractSpringMatcher { } void doMatch(Object actual) { - matcher.accept(new InternalMatcher(jsonTransformer.apply(actual), path, "", configuration)); + Object json = jsonTransformer.apply(actual); + String pathPrefix = JsonUtils.getPathPrefix(json); + matcher.accept(new InternalMatcher(json, pathPrefix.isEmpty() ? path : Path.create("", pathPrefix), "", configuration)); } } diff --git a/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatchers.java b/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatchers.java index 1da87f10..731927ce 100644 --- a/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatchers.java +++ b/json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/AbstractSpringMatchers.java @@ -79,7 +79,7 @@ public ME node(String newPath) { */ @NotNull public ME inPath(String path) { - return matchers(this.path, configuration, json -> JsonPathAdapter.inPath(json, path)); + return matchers(this.path, configuration, json -> JsonPathAdapter.inPath(jsonTransformer.apply(json), path)); } /** diff --git a/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/MockMvcTest.java b/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/MockMvcTest.java index d7feae5e..ca77ae9b 100644 --- a/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/MockMvcTest.java +++ b/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/MockMvcTest.java @@ -47,6 +47,7 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import java.util.List; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {SpringConfig.class}) @@ -84,10 +85,29 @@ void shouldSupportJsonPathError() throws Exception { exec("/sampleProduces").andExpect(json().inPath("$.result.array[1]").isEqualTo(3)) ).hasMessage(""" JSON documents are different: - Different value found in node "", expected: <3> but was: <2>. + Different value found in node "$.result.array[1]", expected: <3> but was: <2>. """); } + @Test + void shouldSupportJsonPathChainedError() { + assertThatThrownBy(() -> + exec("/sampleProduces").andExpect(json().inPath("$.result").inPath("$.array[*]").isEqualTo(List.of(1, 3, 3))) + ).hasMessage(""" + JSON documents are different: + Different value found in node "$.result.array[*][1]", expected: <3> but was: <2>. + """); + } + + @Test + void shouldSupportJsonPathChainedWithNodeError() { + assertThatThrownBy(() -> + exec("/sampleProduces").andExpect(json().node("result").inPath("$.array[1]").isEqualTo(3)) + ).hasMessage(""" + JSON documents are different: + Different value found in node "$.result.array[*][1]", expected: <3> but was: <2>. + """); + } @Test void shouldPassIfEqualsWithIsoEncoding() throws Exception {