marcingrzejszczak / jsonassert

Simple library to provide fluent interface for JSON assertions
Apache License 2.0
62 stars 9 forks source link

InvalidPathException after upgrade to latest jsonassert version #57

Closed ArjanSchouten closed 11 months ago

ArjanSchouten commented 3 years ago

I discovered an issue in spring-cloud-contract after I upgraded to org.springframework.cloud:spring-cloud-contract-gradle-plugin:3.0.3. One of the tests which was generated looks something like this:

assertThatJson("{\"id\": 10}").field("[\"id\"]").matches("-?(\\d*\\.\\d+|\\d+)");

With the older version of spring-cloud-contract everything works fine. With the newer version however, I get the following exception:

com.jayway.jsonpath.InvalidPathException: Failed to parse filter: [?(@.['id'] =~ /-?(\d*\.\d+|\d+)/)], error on position: 15, char: /
java.lang.RuntimeException: com.jayway.jsonpath.InvalidPathException: Failed to parse filter: [?(@.['id'] =~ /-?(\d*\.\d+|\d+)/)], error on position: 15, char: /
    at com.toomuchcoding.jsonassert.JsonAsserter.parseJsonPathAsArray(JsonAsserter.java:262)

When I explicitly switch back to version 2.4.0 of jsonpath it works again:

    implementation("com.jayway.jsonpath:json-path") {
        version {
            strictly '2.4.0'
        }
    }

Since I don't have much experience with jsonpath, @marcingrzejszczak is jsonassert library generating an invalid json path or is the jsonpath library interpreting the filter the wrong way?

The spring cloud contract groovy file looks like this:

package some_package

import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.spec.internal.MediaTypes

Contract.make {
    request {
        method POST()
        urlPath('/api/v1/something')
        headers {
            header(accept(), applicationJson())
        }
        body(
            something: $(consumer(nonEmpty()), producer('name'))
        )
    }
    response {
        headers {
            header(contentType(), applicationJson())
        }
        status CREATED()
        body(
            id: $(consumer(42), producer(number()))
        )
    }
}
marcingrzejszczak commented 3 years ago

IMO this must be jsonpath. I've already seen similar issues like that. Isn't this similar to https://github.com/tomakehurst/wiremock/issues/1492#issuecomment-840529178 ?

ArjanSchouten commented 3 years ago

Thanks for the quick response. Looks like the same problem indeed. So in https://github.com/json-path/JsonPath/pull/661 it must be fixed if I understand correctly. Hopefully it will be released soon 🤞.

marwin1991 commented 1 year ago

@marcingrzejszczak was it fix? I'm still getting this error altho I use version 0.6.2

            assertThatJson(parsedJson).field("['responseHeader']").field("['sendDate']").matches("([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\\.\\d+)?(Z|[+-][01]\\d:[0-5]\\d)");
java.lang.RuntimeException: com.jayway.jsonpath.InvalidPathException: Failed to parse filter: [?(@.['sendDate'] =~ /([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d+)?(Z|[+-][01]\d:[0-5]\d)/)], error on position: 21, char: /

    at com.toomuchcoding.jsonassert.JsonAsserter.parseJsonPathAsArray(JsonAsserter.java:262)
    at com.toomuchcoding.jsonassert.JsonAsserter.jsonPathToArray(JsonAsserter.java:254)
    at com.toomuchcoding.jsonassert.JsonAsserter.check(JsonAsserter.java:226)
    at com.toomuchcoding.jsonassert.JsonAsserter.checkBufferedJsonPathString(JsonAsserter.java:267)
    at com.toomuchcoding.jsonassert.JsonAsserter.matches(JsonAsserter.java:176)
    at ........
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: com.jayway.jsonpath.InvalidPathException: Failed to parse filter: [?(@.['sendDate'] =~ /([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d+)?(Z|[+-][01]\d:[0-5]\d)/)], error on position: 21, char: /
    at com.jayway.jsonpath.internal.filter.FilterCompiler.compile(FilterCompiler.java:89)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.compile(FilterCompiler.java:54)
    at com.jayway.jsonpath.internal.path.PathCompiler.readFilterToken(PathCompiler.java:461)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:141)
    at com.jayway.jsonpath.internal.path.PathCompiler.readBracketPropertyToken(PathCompiler.java:617)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:138)
    at com.jayway.jsonpath.internal.path.PathCompiler.readDotToken(PathCompiler.java:171)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:145)
    at com.jayway.jsonpath.internal.path.PathCompiler.readContextToken(PathCompiler.java:124)
    at com.jayway.jsonpath.internal.path.PathCompiler.compile(PathCompiler.java:58)
    at com.jayway.jsonpath.internal.path.PathCompiler.compile(PathCompiler.java:75)
    at com.jayway.jsonpath.JsonPath.<init>(JsonPath.java:97)
    at com.jayway.jsonpath.JsonPath.compile(JsonPath.java:463)
    at com.jayway.jsonpath.internal.JsonContext.pathFromCache(JsonContext.java:222)
    at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:78)
    at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:83)
    at com.toomuchcoding.jsonassert.JsonAsserter.parseJsonPathAsArray(JsonAsserter.java:259)
    ... 72 more
[INFO] |  +- com.toomuchcoding.jsonassert:jsonassert:jar:0.6.2:test
[INFO]    +- com.jayway.jsonpath:json-path:jar:2.5.0:compile
jakub-bochenski commented 1 year ago

Is there a way to work around this? Should I downgrade jsonpath to 2.4.0 for now?

FTR my case is

            assertThatJson(parsedJson).field("['userId']").matches("-?(\\d+)");

Failed to parse filter: [?(@.['userId'] =~ /-?(\d+)/)], error on position: 19, char: /
jakub-bochenski commented 1 year ago

Yes, downgrading to 2.4.0 seems to fix it

marcingrzejszczak commented 1 year ago

I've taken all the examples you've presented with the latest 0.6.2 version and all tests are passing with json path 2.7.0. Can someone create a sample that replicates this issue?

marcingrzejszczak commented 1 year ago
[INFO]    +- com.jayway.jsonpath:json-path:jar:2.5.0:compile

It seems that your setup is wrong and you take in an old version of json-path