From cf2e7e0feb8f227d937e6aab6061e91b0a44d62b Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Tue, 25 Apr 2017 14:57:07 +0200 Subject: [PATCH 1/2] Generate code that respects dots in keys without this change if the user has jsons that contain `.` in a key (e.g. `foo.bar.baz`) then the produced json path is wrong with this change we're wrapping all keys in `[' ']` format (e.g. `['foo.bar.baz']`) so that the json path gets properly translated fixes #269 --- .../util/DelegatingJsonVerifiable.java | 20 ++- .../builder/ContractHttpDocsSpec.groovy | 2 +- .../JaxRsClientMethodBuilderSpec.groovy | 88 ++++++------ .../MockMvcMethodBodyBuilderSpec.groovy | 124 ++++++++-------- .../util/JsonToJsonPathsConverterSpec.groovy | 132 +++++++++--------- 5 files changed, 187 insertions(+), 179 deletions(-) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java index 792ccb1d99..9fdaf5ce88 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java @@ -16,12 +16,12 @@ package org.springframework.cloud.contract.verifier.util; -import static org.apache.commons.lang3.StringEscapeUtils.escapeJava; +import com.toomuchcoding.jsonassert.JsonVerifiable; import java.util.LinkedList; import java.util.regex.Pattern; -import com.toomuchcoding.jsonassert.JsonVerifiable; +import static org.apache.commons.lang3.StringEscapeUtils.escapeJava; /** * Implementation of the {@link MethodBufferingJsonVerifiable} that contains a list @@ -84,9 +84,9 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { Object valueToPut = value instanceof ShouldTraverse ? ((ShouldTraverse) value).value : value; DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(valueToPut), this.methodsBuffer); if (this.delegate.isIteratingOverArray() && !(value instanceof ShouldTraverse)) { - verifiable.appendMethodWithQuotedValue("contains", valueToPut); + verifiable.appendMethodWithQuotedValue("contains", wrapInBrackets(valueToPut)); } else { - verifiable.appendMethodWithQuotedValue("field", valueToPut); + verifiable.appendMethodWithQuotedValue("field", wrapInBrackets(valueToPut)); } return verifiable; } @@ -103,14 +103,14 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable array(Object value) { DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(value), this.methodsBuffer); - verifiable.appendMethodWithQuotedValue("array", value); + verifiable.appendMethodWithQuotedValue("array", wrapInBrackets(value)); return verifiable; } @Override public MethodBufferingJsonVerifiable arrayField(Object value) { DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(value).arrayField(), this.methodsBuffer); - verifiable.appendMethodWithQuotedValue("array", value); + verifiable.appendMethodWithQuotedValue("array", wrapInBrackets(value)); return verifiable; } @@ -289,6 +289,14 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { return this.delegate.isAssertingAValueInArray(); } + // Related to https://github.com/spring-cloud/spring-cloud-contract/issues/269 + private Object wrapInBrackets(Object name) { + if (name instanceof Number) { + return name; + } + return "['" + name.toString() + "']"; + } + @Override public String method() { return createMethodString(); diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy index 6d790dd757..81935cdf3f 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy @@ -279,7 +279,7 @@ class ContractHttpDocsSpec extends Specification { response.header('Content-Type') == 'application/json' and: DocumentContext parsedJson = JsonPath.parse(response.body.asString()) - assertThatJson(parsedJson).field("code").matches("(123123)?") + assertThatJson(parsedJson).field("['code']").matches("(123123)?") """ // end::optionals_test[] stripped(blockBuilder.toString()) == stripped(expectedTest) diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy index 48c81a82cc..454120961d 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy @@ -52,8 +52,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -86,9 +86,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property3").isEqualTo(false)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").isNull()""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("true")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") and: stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub()) and: @@ -123,9 +123,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("a").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub()) and: @@ -162,10 +162,10 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("a").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").hasSize(2)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub()) and: @@ -261,8 +261,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("property1").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("property2").isEqualTo("b")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -295,8 +295,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property1").contains("property2").isEqualTo("test1")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property1").contains("property3").isEqualTo("test2")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -329,8 +329,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").field("property3").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -368,8 +368,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -400,8 +400,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -521,8 +521,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains(modifyStringIfRequired.call("queryParam('age', '99'")) test.contains(modifyStringIfRequired.call("queryParam('name', 'Denis.Stepanov'")) test.contains(modifyStringIfRequired.call("queryParam('email', 'bob@email.com'")) - test.contains(modifyStringIfRequired.call("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""")) - test.contains(modifyStringIfRequired.call("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""")) + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -578,8 +578,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains(modifyStringIfRequired.call("queryParam('age', '99'")) test.contains(modifyStringIfRequired.call("queryParam('name', 'Denis.Stepanov'")) test.contains(modifyStringIfRequired.call("queryParam('email', 'bob@email.com'")) - test.contains(modifyStringIfRequired.call("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""")) - test.contains(modifyStringIfRequired.call("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""")) + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -743,7 +743,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub assertThat(response.getStatus()).isEqualTo(200); // and: DocumentContext parsedJson = JsonPath.parse(responseAsString); - assertThatJson(parsedJson).field("property1").isEqualTo("a"); + assertThatJson(parsedJson).field("['property1']").isEqualTo("a"); ''' // end::jaxrs[] stripped(test) == stripped(expectedResponse) @@ -966,8 +966,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -1037,21 +1037,21 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('assertThatJson(parsedJson).field("aBoolean").matches("(true|false)")') - test.contains('assertThatJson(parsedJson).field("alpha").matches("[\\\\p{L}]*")') - test.contains('assertThatJson(parsedJson).field("hostname").matches("((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?")') - test.contains('assertThatJson(parsedJson).field("url").matches("^(?:(?:[A-Za-z][+-.\\\\w^_]*:/{2})?(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,})))(?::\\\\d{2,5})?(?:/\\\\S*)?)') - test.contains('assertThatJson(parsedJson).field("number").matches("-?\\\\d*(\\\\.\\\\d+)?")') - test.contains('assertThatJson(parsedJson).field("email").matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}")') - test.contains('assertThatJson(parsedJson).field("ip").matches("([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])")') - test.contains('assertThatJson(parsedJson).field("uuid").matches("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}")') - test.contains('assertThatJson(parsedJson).field("date").matches("(\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")') - test.contains('assertThatJson(parsedJson).field("dateTime").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])")') - test.contains('assertThatJson(parsedJson).field("time").matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])")') - test.contains('assertThatJson(parsedJson).field("iso8601WithOffset").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{3})?(Z|[+-][01]\\\\d:[0-5]\\\\d)")') - test.contains('assertThatJson(parsedJson).field("nonBlankString").matches(".*(\\\\S+|\\\\R).*|!^\\\\R*' + endOfLineRegexSymbol + '")') - test.contains('assertThatJson(parsedJson).field("nonEmptyString").matches(".+")') - test.contains('assertThatJson(parsedJson).field("anyOf").matches("^foo' + endOfLineRegexSymbol + '|^bar' + endOfLineRegexSymbol + '")') + test.contains('assertThatJson(parsedJson).field("[\'aBoolean\']").matches("(true|false)")') + test.contains('assertThatJson(parsedJson).field("[\'alpha\']").matches("[\\\\p{L}]*")') + test.contains('assertThatJson(parsedJson).field("[\'hostname\']").matches("((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?")') + test.contains('assertThatJson(parsedJson).field("[\'url\']").matches("^(?:(?:[A-Za-z][+-.\\\\w^_]*:/{2})?(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,})))(?::\\\\d{2,5})?(?:/\\\\S*)?)') + test.contains('assertThatJson(parsedJson).field("[\'number\']").matches("-?\\\\d*(\\\\.\\\\d+)?")') + test.contains('assertThatJson(parsedJson).field("[\'email\']").matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}")') + test.contains('assertThatJson(parsedJson).field("[\'ip\']").matches("([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])")') + test.contains('assertThatJson(parsedJson).field("[\'uuid\']").matches("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}")') + test.contains('assertThatJson(parsedJson).field("[\'date\']").matches("(\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")') + test.contains('assertThatJson(parsedJson).field("[\'dateTime\']").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])")') + test.contains('assertThatJson(parsedJson).field("[\'time\']").matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])")') + test.contains('assertThatJson(parsedJson).field("[\'iso8601WithOffset\']").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{3})?(Z|[+-][01]\\\\d:[0-5]\\\\d)")') + test.contains('assertThatJson(parsedJson).field("[\'nonBlankString\']").matches(".*(\\\\S+|\\\\R).*|!^\\\\R*' + endOfLineRegexSymbol + '")') + test.contains('assertThatJson(parsedJson).field("[\'nonEmptyString\']").matches(".+")') + test.contains('assertThatJson(parsedJson).field("[\'anyOf\']").matches("^foo' + endOfLineRegexSymbol + '|^bar' + endOfLineRegexSymbol + '")') !test.contains('cursor') !test.contains('REGEXP>>') and: diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy index 3ce11ed3a8..7c15e45f2f 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy @@ -127,8 +127,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -161,9 +161,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("true")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").isNull()""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property3").isEqualTo(false)""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -198,9 +198,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("a").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -237,10 +237,10 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("a").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").hasSize(2)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -336,8 +336,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property").field(7).isEqualTo(0.0)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property").field(14).isEqualTo(0.0)""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").field(7).isEqualTo(0.0)""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").field(14).isEqualTo(0.0)""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -371,8 +371,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("property2").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -405,8 +405,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property1").contains("property2").isEqualTo("test1")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property1").contains("property3").isEqualTo("test2")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -439,8 +439,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").field("property3").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -477,8 +477,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -511,8 +511,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -546,7 +546,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub when: builder.appendTo(blockBuilder) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property").matches("\\\\d+")""") + blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").matches("\\\\d+")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -602,8 +602,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains('''.queryParam("name","Denis.Stepanov")''') test.contains('''.queryParam("email","bob@email.com")''') test.contains('''.get("/users")''') - test.contains('assertThatJson(parsedJson).field("property1").isEqualTo("a")') - test.contains('assertThatJson(parsedJson).field("property2").isEqualTo("b")') + test.contains('assertThatJson(parsedJson).field("[\'property1\']").isEqualTo("a")') + test.contains('assertThatJson(parsedJson).field("[\'property2\']").isEqualTo("b")') and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -660,8 +660,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains('''.queryParam("name","Denis.Stepanov")''') test.contains('''.queryParam("email","bob@email.com")''') test.contains('''.get("/foo/123456")''') - test.contains('assertThatJson(parsedJson).field("property1").isEqualTo("a")') - test.contains('assertThatJson(parsedJson).field("property2").isEqualTo("b")') + test.contains('assertThatJson(parsedJson).field("[\'property1\']").isEqualTo("a")') + test.contains('assertThatJson(parsedJson).field("[\'property2\']").isEqualTo("b")') and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -844,8 +844,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains("""assertThatJson(parsedJson).array("errors").contains("property").isEqualTo("bank_account_number")""") - test.contains("""assertThatJson(parsedJson).array("errors").contains("message").isEqualTo("incorrect_format")""") + test.contains("""assertThatJson(parsedJson).array("['errors']").contains("['property']").isEqualTo("bank_account_number")""") + test.contains("""assertThatJson(parsedJson).array("['errors']").contains("['message']").isEqualTo("incorrect_format")""") and: stubMappingIsValidWireMockStub(contractDsl) and: @@ -923,7 +923,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains("""assertThatJson(parsedJson).field("message").matches("User not found by email = \\\\\\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\\\\\.[a-zA-Z]{2,4}\\\\\\\\]")""") + test.contains("""assertThatJson(parsedJson).field("['message']").matches("User not found by email = \\\\\\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\\\\\.[a-zA-Z]{2,4}\\\\\\\\]")""") and: // no static compilation due to bug in Groovy https://issues.apache.org/jira/browse/GROOVY-8055 SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) @@ -943,7 +943,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub def test = blockBuilder.toString() then: test.contains('''"email":"abc@abc.com"''') - test.contains("""assertThatJson(parsedJson).field("code").matches("(123123)?")""") + test.contains("""assertThatJson(parsedJson).field("['code']").matches("(123123)?")""") !test.contains('''REGEXP''') !test.contains('''OPTIONAL''') !test.contains('''OptionalProperty''') @@ -963,7 +963,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub def test = blockBuilder.toString() then: test.contains('\\"email\\":\\"abc@abc.com\\"') - test.contains('assertThatJson(parsedJson).field("code").matches("(123123)?");') + test.contains('assertThatJson(parsedJson).field("[\'code\']").matches("(123123)?");') !test.contains('''REGEXP''') !test.contains('''OPTIONAL''') !test.contains('''OptionalProperty''') @@ -1274,7 +1274,7 @@ World.'''""" builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('''assertThatJson(parsedJson).array("authorities").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+\\$").value()''') + test.contains('''assertThatJson(parsedJson).array("[\'authorities']").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+\\$").value()''') and: SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @@ -1310,7 +1310,7 @@ World.'''""" builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('''assertThatJson(parsedJson).array("authorities").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+$").value()''') + test.contains('''assertThatJson(parsedJson).array("[\'authorities']").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+$").value()''') and: SyntaxChecker.tryToCompileJava(blockBuilder.toString()) } @@ -1337,7 +1337,7 @@ World.'''""" builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - !test.contains('''assertThatJson(parsedJson).field("rejectionReason").isEqualTo("assertThatRejectionReasonIsNull("''') + !test.contains('''assertThatJson(parsedJson).field("[\'rejectionReason']").isEqualTo("assertThatRejectionReasonIsNull("''') test.contains('''assertThatRejectionReasonIsNull(''') where: methodBuilderName | methodBuilder @@ -1373,7 +1373,7 @@ World.'''""" builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('assertThatJson(parsedJson).array().contains("id").matches("[0-9]+")') + test.contains('assertThatJson(parsedJson).array().contains("[\'id\']").matches("[0-9]+")') and: SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @@ -1540,8 +1540,8 @@ World.'''""" builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('assertThatJson(parsedJson).array("partners").array("payment_methods").arrayField().isEqualTo("BANK").value()') - test.contains('assertThatJson(parsedJson).array("partners").array("payment_methods").arrayField().isEqualTo("CASH").value()') + test.contains('assertThatJson(parsedJson).array("[\'partners\']").array("[\'payment_methods\']").arrayField().isEqualTo("BANK").value()') + test.contains('assertThatJson(parsedJson).array("[\'partners\']").array("[\'payment_methods\']").arrayField().isEqualTo("CASH").value()') and: SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: @@ -1569,7 +1569,7 @@ World.'''""" builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('assertThatJson(parsedJson).field("message").matches("^(?!\\\\s*\\$).+")') + test.contains('assertThatJson(parsedJson).field("[\'message\']").matches("^(?!\\\\s*\\$).+")') and: SyntaxChecker.tryToCompileGroovy(blockBuilder.toString(), false) } @@ -1661,7 +1661,7 @@ World.'''""" strippedTest.matches(""".*put\\("/foo/[0-9]{5}"\\).*""") strippedTest.contains("""response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application/vnd\\\\.fraud\\\\.v1\\\\+json.*')""") "application/vnd.fraud.v1+json;charset=UTF-8".matches('application/vnd\\.fraud\\.v1\\+json.*') - strippedTest.contains("""assertThatJson(parsedJson).field("responseElement").matches("[0-9]{7}")""") + strippedTest.contains("""assertThatJson(parsedJson).field("['responseElement']").matches("[0-9]{7}")""") and: SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @@ -1938,21 +1938,21 @@ World.'''""" builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('assertThatJson(parsedJson).field("aBoolean").matches("(true|false)")') - test.contains('assertThatJson(parsedJson).field("alpha").matches("[\\\\p{L}]*")') - test.contains('assertThatJson(parsedJson).field("hostname").matches("((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?")') - test.contains('assertThatJson(parsedJson).field("url").matches("^(?:(?:[A-Za-z][+-.\\\\w^_]*:/{2})?(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,})))(?::\\\\d{2,5})?(?:/\\\\S*)?)') - test.contains('assertThatJson(parsedJson).field("number").matches("-?\\\\d*(\\\\.\\\\d+)?")') - test.contains('assertThatJson(parsedJson).field("email").matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}")') - test.contains('assertThatJson(parsedJson).field("ip").matches("([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])")') - test.contains('assertThatJson(parsedJson).field("uuid").matches("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}")') - test.contains('assertThatJson(parsedJson).field("date").matches("(\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])') - test.contains('assertThatJson(parsedJson).field("dateTime").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])') - test.contains('assertThatJson(parsedJson).field("time").matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])")') - test.contains('assertThatJson(parsedJson).field("iso8601WithOffset").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{3})?(Z|[+-][01]\\\\d:[0-5]\\\\d)")') - test.contains('assertThatJson(parsedJson).field("nonBlankString").matches(".*(\\\\S+|\\\\R).*|!^\\\\R*' + endOfLineRegExSymbol + '")') - test.contains('assertThatJson(parsedJson).field("nonEmptyString").matches(".+")') - test.contains('assertThatJson(parsedJson).field("anyOf").matches("^foo' + endOfLineRegExSymbol + '|^bar' + endOfLineRegExSymbol + '")') + test.contains('assertThatJson(parsedJson).field("[\'aBoolean\']").matches("(true|false)")') + test.contains('assertThatJson(parsedJson).field("[\'alpha\']").matches("[\\\\p{L}]*")') + test.contains('assertThatJson(parsedJson).field("[\'hostname\']").matches("((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?")') + test.contains('assertThatJson(parsedJson).field("[\'url\']").matches("^(?:(?:[A-Za-z][+-.\\\\w^_]*:/{2})?(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,})))(?::\\\\d{2,5})?(?:/\\\\S*)?)') + test.contains('assertThatJson(parsedJson).field("[\'number\']").matches("-?\\\\d*(\\\\.\\\\d+)?")') + test.contains('assertThatJson(parsedJson).field("[\'email\']").matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}")') + test.contains('assertThatJson(parsedJson).field("[\'ip\']").matches("([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])")') + test.contains('assertThatJson(parsedJson).field("[\'uuid\']").matches("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}")') + test.contains('assertThatJson(parsedJson).field("[\'date\']").matches("(\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])') + test.contains('assertThatJson(parsedJson).field("[\'dateTime\']").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])') + test.contains('assertThatJson(parsedJson).field("[\'time\']").matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])")') + test.contains('assertThatJson(parsedJson).field("[\'iso8601WithOffset\']").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{3})?(Z|[+-][01]\\\\d:[0-5]\\\\d)")') + test.contains('assertThatJson(parsedJson).field("[\'nonBlankString\']").matches(".*(\\\\S+|\\\\R).*|!^\\\\R*' + endOfLineRegExSymbol + '")') + test.contains('assertThatJson(parsedJson).field("[\'nonEmptyString\']").matches(".+")') + test.contains('assertThatJson(parsedJson).field("[\'anyOf\']").matches("^foo' + endOfLineRegExSymbol + '|^bar' + endOfLineRegExSymbol + '")') !test.contains('cursor') !test.contains('REGEXP>>') and: @@ -2066,7 +2066,7 @@ DocumentContext parsedJson = JsonPath.parse(json); builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - !test.contains('assertThatJson(parsedJson).field("a").isEqualTo(1)') + !test.contains('assertThatJson(parsedJson).field("[\'a\']").isEqualTo(1)') test.contains(expectedAssertion) and: SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) @@ -2103,8 +2103,8 @@ DocumentContext parsedJson = JsonPath.parse(json); builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: -// test.contains('assertThatJson(parsedJson).field("bar").matches("some value \\"with quote\\"|bar")') -// and: + test.contains('assertThatJson(parsedJson).field("[\'bar\']").matches("some value \\"with quote\\"|bar")') + and: SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: //order is inverted cause Intellij didn't parse this properly @@ -2172,8 +2172,8 @@ DocumentContext parsedJson = JsonPath.parse(json); when: SyntaxChecker.tryToCompile(methodBuilderName, test) then: - test.contains('assertThatJson(parsedJson).array("list").isEmpty()') - !test.contains('assertThatJson(parsedJson).array("foo").isEmpty()') + test.contains('assertThatJson(parsedJson).array("[\'list\']").isEmpty()') + !test.contains('assertThatJson(parsedJson).array("[\'foo\']").isEmpty()') where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy index 962626236f..e5a1bb2e5f 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy @@ -38,23 +38,23 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method() == """.array().field("some").field("nested").field("json").isEqualTo("with value")""" && + it.method() == """.array().field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" && it.jsonPath() == '''$[*].some.nested[?(@.json == 'with value')]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").field("anothervalue").isEqualTo(4)""" && + it.method() == """.array().field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" && it.jsonPath() == '''$[*].some.nested[?(@.anothervalue == 4)]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1")""" && + it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" && it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name1')]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name2")""" && + it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" && it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name2')]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").array("withlist").field("anothernested").field("name").isEqualTo("name3")""" && + it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").field("['anothernested']").field("['name']").isEqualTo("name3")""" && it.jsonPath() == '''$[*].some.nested.withlist[*].anothernested[?(@.name == 'name3')]''' } and: @@ -131,19 +131,19 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method() == """.field("some").field("nested").field("json").isEqualTo("with value")""" && + it.method() == """.field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" && it.jsonPath() == '''$.some.nested[?(@.json == 'with value')]''' } pathAndValues.find { - it.method() == """.field("some").field("nested").field("anothervalue").isEqualTo(4)""" && + it.method() == """.field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" && it.jsonPath() == '''$.some.nested[?(@.anothervalue == 4)]''' } pathAndValues.find { - it.method() == """.field("some").field("nested").array("withlist").contains("name").isEqualTo("name1")""" && + it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" && it.jsonPath() == '''$.some.nested.withlist[*][?(@.name == 'name1')]''' } pathAndValues.find { - it.method() == """.field("some").field("nested").array("withlist").contains("name").isEqualTo("name2")""" && + it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" && it.jsonPath() == '''$.some.nested.withlist[*][?(@.name == 'name2')]''' } and: @@ -161,7 +161,7 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method() == """.array("items").arrayField().isEqualTo("HOP").value()""" && + it.method() == """.array("['items']").arrayField().isEqualTo("HOP").value()""" && it.jsonPath() == '''$.items[?(@ == 'HOP')]''' } and: @@ -180,11 +180,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method() == """.field("property1").isNull()""" && + it.method() == """.field("['property1']").isNull()""" && it.jsonPath() == '''$[?(@.property1 == null)]''' } pathAndValues.find { - it.method() == """.field("property2").isEqualTo(true)""" && + it.method() == """.field("['property2']").isEqualTo(true)""" && it.jsonPath() == '''$[?(@.property2 == true)]''' } } @@ -199,15 +199,15 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method() == """.field("extensions").field("7").isEqualTo(28.00)""" && + it.method() == """.field("['extensions']").field("['7']").isEqualTo(28.00)""" && it.jsonPath() == '''$.extensions[?(@.7 == 28.00)]''' } pathAndValues.find { - it.method() == """.field("extensions").field("14").isEqualTo(41.00)""" && + it.method() == """.field("['extensions']").field("['14']").isEqualTo(41.00)""" && it.jsonPath() == '''$.extensions[?(@.14 == 41.00)]''' } pathAndValues.find { - it.method() == """.field("extensions").field("30").isEqualTo(60.00)""" && + it.method() == """.field("['extensions']").field("['30']").isEqualTo(60.00)""" && it.jsonPath() == '''$.extensions[?(@.30 == 60.00)]''' } and: @@ -228,15 +228,15 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method() == """.array("errors").contains("property").isEqualTo("email")""" && + it.method() == """.array("['errors']").contains("['property']").isEqualTo("email")""" && it.jsonPath() == '''$.errors[*][?(@.property == 'email')]''' } pathAndValues.find { - it.method() == """.array("errors").contains("message").isEqualTo("inconsistent value")""" && + it.method() == """.array("['errors']").contains("['message']").isEqualTo("inconsistent value")""" && it.jsonPath() == '''$.errors[*][?(@.message == 'inconsistent value')]''' } pathAndValues.find { - it.method() == """.array("errors").contains("message").isEqualTo("inconsistent value2")""" && + it.method() == """.array("['errors']").contains("['message']").isEqualTo("inconsistent value2")""" && it.jsonPath() == '''$.errors[*][?(@.message == 'inconsistent value2')]''' } and: @@ -279,23 +279,23 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method() == """.array().field("some").field("nested").field("json").isEqualTo("with value")""" && + it.method() == """.array().field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" && it.jsonPath() == '''$[*].some.nested[?(@.json == 'with value')]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").field("anothervalue").isEqualTo(4)""" && + it.method() == """.array().field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" && it.jsonPath() == '''$[*].some.nested[?(@.anothervalue == 4)]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1")""" && + it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" && it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name1')]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name2")""" && + it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" && it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name2')]''' } pathAndValues.find { - it.method() == """.array().field("some").field("nested").array("withlist").field("anothernested").field("name").matches("[a-zA-Z]+")""" && + it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").field("['anothernested']").field("['name']").matches("[a-zA-Z]+")""" && it.jsonPath() == '''$[*].some.nested.withlist[*].anothernested[?(@.name =~ /[a-zA-Z]+/)]''' } when: @@ -315,11 +315,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.field("property1").isEqualTo("a")""" && + it.method()== """.field("['property1']").isEqualTo("a")""" && it.jsonPath() == """\$[?(@.property1 == 'a')]""" } pathAndValues.find { - it.method()== """.field("property2").isEqualTo("b")""" && + it.method()== """.field("['property2']").isEqualTo("b")""" && it.jsonPath() == """\$[?(@.property2 == 'b')]""" } and: @@ -337,15 +337,15 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.field("property1").isEqualTo("true")""" && + it.method()== """.field("['property1']").isEqualTo("true")""" && it.jsonPath() == """\$[?(@.property1 == 'true')]""" } pathAndValues.find { - it.method()== """.field("property2").isNull()""" && + it.method()== """.field("['property2']").isNull()""" && it.jsonPath() == """\$[?(@.property2 == null)]""" } pathAndValues.find { - it.method()== """.field("property3").isEqualTo(false)""" && + it.method()== """.field("['property3']").isEqualTo(false)""" && it.jsonPath() == """\$[?(@.property3 == false)]""" } and: @@ -365,15 +365,15 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method()== """.field("property1").isEqualTo("a")""" && + it.method()== """.field("['property1']").isEqualTo("a")""" && it.jsonPath() == """\$[?(@.property1 == 'a')]""" } pathAndValues.find { - it.method()== """.array("property2").contains("a").isEqualTo("sth")""" && + it.method()== """.array("['property2']").contains("['a']").isEqualTo("sth")""" && it.jsonPath() == """\$.property2[*][?(@.a == 'sth')]""" } pathAndValues.find { - it.method()== """.array("property2").contains("b").isEqualTo("sthElse")""" && + it.method()== """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" && it.jsonPath() == """\$.property2[*][?(@.b == 'sthElse')]""" } and: @@ -395,19 +395,19 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method()== """.field("property1").isEqualTo("a")""" && + it.method()== """.field("['property1']").isEqualTo("a")""" && it.jsonPath() == """\$[?(@.property1 == 'a')]""" } pathAndValues.find { - it.method()== """.array("property2").contains("a").isEqualTo("sth")""" && + it.method()== """.array("['property2']").contains("['a']").isEqualTo("sth")""" && it.jsonPath() == """\$.property2[*][?(@.a == 'sth')]""" } pathAndValues.find { - it.method()== """.array("property2").hasSize(2)""" && + it.method()== """.array("['property2']").hasSize(2)""" && it.jsonPath() == """\$.property2[*]""" } pathAndValues.find { - it.method()== """.array("property2").contains("b").isEqualTo("sthElse")""" && + it.method()== """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" && it.jsonPath() == """\$.property2[*][?(@.b == 'sthElse')]""" } and: @@ -426,11 +426,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method()== """.field("property").field(7).isEqualTo(0.0)""" && + it.method()== """.field("['property']").field(7).isEqualTo(0.0)""" && it.jsonPath() == """\$.property[?(@.7 == 0.0)]""" } pathAndValues.find { - it.method()== """.field("property").field(14).isEqualTo(0.0)""" && + it.method()== """.field("['property']").field(14).isEqualTo(0.0)""" && it.jsonPath() == """\$.property[?(@.14 == 0.0)]""" } and: @@ -450,11 +450,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.array().contains("property1").isEqualTo("a")""" && + it.method()== """.array().contains("['property1']").isEqualTo("a")""" && it.jsonPath() == """\$[*][?(@.property1 == 'a')]""" } pathAndValues.find { - it.method()== """.array().contains("property2").isEqualTo("b")""" && + it.method()== """.array().contains("['property2']").isEqualTo("b")""" && it.jsonPath() == """\$[*][?(@.property2 == 'b')]""" } and: @@ -476,11 +476,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.array().contains("property1").isEqualTo("a")""" && + it.method()== """.array().contains("['property1']").isEqualTo("a")""" && it.jsonPath() == """\$[*][?(@.property1 == 'a')]""" } pathAndValues.find { - it.method()== """.array().contains("property2").isEqualTo("b")""" && + it.method()== """.array().contains("['property2']").isEqualTo("b")""" && it.jsonPath() == """\$[*][?(@.property2 == 'b')]""" } pathAndValues.find { @@ -503,11 +503,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.array("property1").contains("property2").isEqualTo("test1")""" && + it.method()== """.array("['property1']").contains("['property2']").isEqualTo("test1")""" && it.jsonPath() == """\$.property1[*][?(@.property2 == 'test1')]""" } pathAndValues.find { - it.method()== """.array("property1").contains("property3").isEqualTo("test2")""" && + it.method()== """.array("['property1']").contains("['property3']").isEqualTo("test2")""" && it.jsonPath() == """\$.property1[*][?(@.property3 == 'test2')]""" } and: @@ -528,15 +528,15 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.array("property1").contains("property2").isEqualTo("test1")""" && + it.method()== """.array("['property1']").contains("['property2']").isEqualTo("test1")""" && it.jsonPath() == """\$.property1[*][?(@.property2 == 'test1')]""" } pathAndValues.find { - it.method()== """.array("property1").contains("property3").isEqualTo("test2")""" && + it.method()== """.array("['property1']").contains("['property3']").isEqualTo("test2")""" && it.jsonPath() == """\$.property1[*][?(@.property3 == 'test2')]""" } pathAndValues.find { - it.method()== """.array("property1").hasSize(2)""" && + it.method()== """.array("['property1']").hasSize(2)""" && it.jsonPath() == """\$.property1[*]""" } and: @@ -553,11 +553,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.field("property2").field("property3").isEqualTo("b")""" && + it.method()== """.field("['property2']").field("['property3']").isEqualTo("b")""" && it.jsonPath() == """\$.property2[?(@.property3 == 'b')]""" } pathAndValues.find { - it.method()== """.field("property1").isEqualTo("a")""" && + it.method()== """.field("['property1']").isEqualTo("a")""" && it.jsonPath() == """\$[?(@.property1 == 'a')]""" } and: @@ -574,11 +574,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method()== """.field("property2").matches("[0-9]{3}")""" && + it.method()== """.field("['property2']").matches("[0-9]{3}")""" && it.jsonPath() == """\$[?(@.property2 =~ /[0-9]{3}/)]""" } pathAndValues.find { - it.method()== """.field("property1").isEqualTo("a")""" && + it.method()== """.field("['property1']").isEqualTo("a")""" && it.jsonPath() == """\$[?(@.property1 == 'a')]""" } and: @@ -594,7 +594,7 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method()== """.field("property2").matches("\\\\d+")""" && + it.method()== """.field("['property2']").matches("\\\\d+")""" && it.jsonPath() == """\$[?(@.property2 =~ /\\d+/)]""" } and: @@ -613,11 +613,11 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method()== """.array("errors").contains("property").isEqualTo("bank_account_number")""" && + it.method()== """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" && it.jsonPath() == """\$.errors[*][?(@.property == 'bank_account_number')]""" } pathAndValues.find { - it.method()== """.array("errors").contains("message").isEqualTo("incorrect_format")""" && + it.method()== """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" && it.jsonPath() == """\$.errors[*][?(@.message == 'incorrect_format')]""" } and: @@ -638,15 +638,15 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(json) then: pathAndValues.find { - it.method()== """.array("errors").contains("property").isEqualTo("bank_account_number")""" && + it.method()== """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" && it.jsonPath() == """\$.errors[*][?(@.property == 'bank_account_number')]""" } pathAndValues.find { - it.method()== """.array("errors").contains("message").isEqualTo("incorrect_format")""" && + it.method()== """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" && it.jsonPath() == """\$.errors[*][?(@.message == 'incorrect_format')]""" } pathAndValues.find { - it.method()== """.array("errors").hasSize(1)""" && + it.method()== """.array("['errors']").hasSize(1)""" && it.jsonPath() == """\$.errors[*]""" } and: @@ -674,19 +674,19 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(38.995548)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.995548)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(-77.119759)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-77.119759)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(-76.909393)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-76.909393)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(38.791645)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.791645)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]""" } and: @@ -720,19 +720,19 @@ class JsonToJsonPathsConverterSpec extends Specification { JsonPaths pathAndValues = new JsonToJsonPathsConverter().transformToJsonPathWithTestsSideValues(new JsonSlurper().parseText(json)) then: pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(38.995548)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.995548)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(-77.119759)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-77.119759)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(-76.909393)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-76.909393)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(38.791645)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.791645)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]""" } pathAndValues.find { @@ -740,11 +740,11 @@ class JsonToJsonPathsConverterSpec extends Specification { it.jsonPath() == """\$""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().hasSize(2)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().hasSize(2)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*]""" } pathAndValues.find { - it.method()== """.array().field("place").field("bounding_box").array("coordinates").hasSize(1)""" && + it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").hasSize(1)""" && it.jsonPath() == """\$[*].place.bounding_box.coordinates[*]""" } and: From cf52e6baa62795d4963a1dc129aca6a908fcf052 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Wed, 26 Apr 2017 12:12:17 +0200 Subject: [PATCH 2/2] Added support fot dots in keys without this change it's impossible to work with jsons that have dots in keys with this change that's possible again fixes #269 --- .../loan/model/FraudServiceRequest.java | 3 + .../loan/model/FraudServiceResponse.java | 3 + .../com/example/fraud/model/FraudCheck.java | 3 + .../example/fraud/model/FraudCheckResult.java | 3 + .../fraud/shouldMarkClientAsFraud.groovy | 4 +- .../fraud/shouldMarkClientAsNotFraud.groovy | 4 +- .../DslToWireMockClientConverterSpec.groovy | 54 +++---- .../JUnitMessagingMethodBodyBuilder.groovy | 2 +- .../builder/JUnitMethodBodyBuilder.groovy | 2 +- .../verifier/builder/MethodBodyBuilder.groovy | 36 ++++- .../RestAssuredJUnitMethodBodyBuilder.groovy | 2 +- .../SpockMessagingMethodBodyBuilder.groovy | 2 +- ...kMethodRequestProcessingBodyBuilder.groovy | 4 +- .../util/DelegatingJsonVerifiable.java | 17 ++- .../util/JsonToJsonPathsConverter.groovy | 14 +- .../JaxRsClientMethodBuilderSpec.groovy | 27 +++- .../builder/MethodBodyBuilderSpec.groovy | 49 +++++- .../MockMvcMethodBodyBuilderSpec.groovy | 12 +- ...vcMethodBodyBuilderWithMatchersSpec.groovy | 11 +- .../verifier/dsl/WireMockGroovyDslSpec.groovy | 104 +++++++++---- .../util/JsonToJsonPathsConverterSpec.groovy | 143 ++++++++++-------- 21 files changed, 343 insertions(+), 156 deletions(-) diff --git a/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java b/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java index 0230540131..5cc40027bb 100644 --- a/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java +++ b/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceRequest.java @@ -1,9 +1,12 @@ package com.example.loan.model; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.math.BigDecimal; public class FraudServiceRequest { + @JsonProperty("client.id") private String clientId; private BigDecimal loanAmount; diff --git a/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java b/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java index 50e64478b9..af58a03223 100644 --- a/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java +++ b/samples/standalone/dsl/http-client/src/main/java/com/example/loan/model/FraudServiceResponse.java @@ -1,9 +1,12 @@ package com.example.loan.model; +import com.fasterxml.jackson.annotation.JsonProperty; + public class FraudServiceResponse { private FraudCheckStatus fraudCheckStatus; + @JsonProperty("rejection.reason") private String rejectionReason; public FraudServiceResponse() { diff --git a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheck.java b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheck.java index b0210573e2..e98c2b60d2 100644 --- a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheck.java +++ b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheck.java @@ -1,9 +1,12 @@ package com.example.fraud.model; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.math.BigDecimal; public class FraudCheck { + @JsonProperty("client.id") private String clientId; private BigDecimal loanAmount; diff --git a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java index 60b340276a..2f30912063 100644 --- a/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java +++ b/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/model/FraudCheckResult.java @@ -1,9 +1,12 @@ package com.example.fraud.model; +import com.fasterxml.jackson.annotation.JsonProperty; + public class FraudCheckResult { private FraudCheckStatus fraudCheckStatus; + @JsonProperty("rejection.reason") private String rejectionReason; public FraudCheckResult() { diff --git a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy index e798cdc7eb..844232c456 100644 --- a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy +++ b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy @@ -5,7 +5,7 @@ org.springframework.cloud.contract.spec.Contract.make { method 'PUT' // (2) url '/fraudcheck' // (3) body([ // (4) - clientId: $(regex('[0-9]{10}')), + "client.id": $(regex('[0-9]{10}')), loanAmount: 99999 ]) headers { // (5) @@ -16,7 +16,7 @@ org.springframework.cloud.contract.spec.Contract.make { status 200 // (7) body([ // (8) fraudCheckStatus: "FRAUD", - rejectionReason: "Amount too high" + "rejection.reason": "Amount too high" ]) headers { // (9) contentType('application/vnd.fraud.v1+json') diff --git a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy index 2b3bea7222..6b87bdc923 100644 --- a/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy +++ b/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsNotFraud.groovy @@ -6,7 +6,7 @@ org.springframework.cloud.contract.spec.Contract.make { url '/fraudcheck' body(""" { - "clientId":"${value(consumer(regex('[0-9]{10}')), producer('1234567890'))}", + "client.id":"${value(consumer(regex('[0-9]{10}')), producer('1234567890'))}", "loanAmount":123.123 } """ @@ -20,7 +20,7 @@ org.springframework.cloud.contract.spec.Contract.make { status 200 body( fraudCheckStatus: "OK", - rejectionReason: $(consumer(null), producer(execute('assertThatRejectionReasonIsNull($it)'))) + "rejection.reason": $(consumer(null), producer(execute('assertThatRejectionReasonIsNull($it)'))) ) headers { header('Content-Type': value( diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy index e5bd1c9539..641986791a 100755 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy @@ -170,37 +170,37 @@ class DslToWireMockClientConverterSpec extends Specification { "url" : "/api/12", "method" : "PUT", "bodyPatterns" : [ { - "matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]" + "matchesJsonPath" : "$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -77.119759)]" }, { - "matchesJsonPath" : "$[*][?(@.text == 'Gonna see you at Warsaw')]" + "matchesJsonPath" : "$[*][?(@.['text'] == 'Gonna see you at Warsaw')]" }, { - "matchesJsonPath" : "$[*].place[?(@.place_type == 'city')]" + "matchesJsonPath" : "$[*].['place'][?(@.['place_type'] == 'city')]" }, { - "matchesJsonPath" : "$[*][?(@.id == 492967299297845248)]" + "matchesJsonPath" : "$[*][?(@.['id'] == 492967299297845248)]" }, { - "matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]" + "matchesJsonPath" : "$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.791645)]" }, { - "matchesJsonPath" : "$[*].place[?(@.country == 'United States')]" + "matchesJsonPath" : "$[*].['place'][?(@.['country'] == 'United States')]" }, { - "matchesJsonPath" : "$[*][?(@.id_str == '492967299297845248')]" + "matchesJsonPath" : "$[*][?(@.['id_str'] == '492967299297845248')]" }, { - "matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]" + "matchesJsonPath" : "$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -76.909393)]" }, { - "matchesJsonPath" : "$[*].place[?(@.name == 'Washington')]" + "matchesJsonPath" : "$[*].['place'][?(@.['name'] == 'Washington')]" }, { - "matchesJsonPath" : "$[*].place.bounding_box[?(@.type == 'Polygon')]" + "matchesJsonPath" : "$[*].['place'].['bounding_box'][?(@.['type'] == 'Polygon')]" }, { - "matchesJsonPath" : "$[*].place[?(@.url == 'http://api.twitter.com/1/geo/id/01fbe706f872cb32.json')]" + "matchesJsonPath" : "$[*].['place'][?(@.['url'] == 'http://api.twitter.com/1/geo/id/01fbe706f872cb32.json')]" }, { - "matchesJsonPath" : "$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]" + "matchesJsonPath" : "$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.995548)]" }, { - "matchesJsonPath" : "$[*].place[?(@.country_code == 'US')]" + "matchesJsonPath" : "$[*].['place'][?(@.['country_code'] == 'US')]" }, { - "matchesJsonPath" : "$[*].place[?(@.full_name == 'Washington, DC')]" + "matchesJsonPath" : "$[*].['place'][?(@.['full_name'] == 'Washington, DC')]" }, { - "matchesJsonPath" : "$[*][?(@.created_at == 'Sat Jul 26 09:38:57 +0000 2014')]" + "matchesJsonPath" : "$[*][?(@.['created_at'] == 'Sat Jul 26 09:38:57 +0000 2014')]" }, { - "matchesJsonPath" : "$[*].place[?(@.id == '01fbe706f872cb32')]" + "matchesJsonPath" : "$[*].['place'][?(@.['id'] == '01fbe706f872cb32')]" } ], "headers" : { "Content-Type" : { @@ -372,9 +372,9 @@ class DslToWireMockClientConverterSpec extends Specification { "url" : "/users/password", "method" : "POST", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.email =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4})?/)]" + "matchesJsonPath" : "$[?(@.['email'] =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4})?/)]" }, { - "matchesJsonPath" : "$[?(@.callback_url =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]" + "matchesJsonPath" : "$[?(@.['callback_url'] =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]" } ], "headers" : { "Content-Type" : { @@ -531,15 +531,15 @@ class DslToWireMockClientConverterSpec extends Specification { } }, "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.valueWithoutAMatcher == 'foo')]" + "matchesJsonPath" : "$[?(@.['valueWithoutAMatcher'] == 'foo')]" }, { - "matchesJsonPath" : "$[?(@.valueWithTypeMatch == 'string')]" + "matchesJsonPath" : "$[?(@.['valueWithTypeMatch'] == 'string')]" }, { - "matchesJsonPath" : "$.list.some.nested[?(@.anothervalue == 4)]" + "matchesJsonPath" : "$.['list'].['some'].['nested'][?(@.['anothervalue'] == 4)]" }, { - "matchesJsonPath" : "$.list.someother.nested[?(@.anothervalue == 4)]" + "matchesJsonPath" : "$.['list'].['someother'].['nested'][?(@.['anothervalue'] == 4)]" }, { - "matchesJsonPath" : "$.list.someother.nested[?(@.json == 'with value')]" + "matchesJsonPath" : "$.['list'].['someother'].['nested'][?(@.['json'] == 'with value')]" }, { "matchesJsonPath" : "$[?(@.duck =~ /([0-9]{3})/)]" }, { @@ -649,8 +649,8 @@ class DslToWireMockClientConverterSpec extends Specification { callback_url: 'http://partners.com' ) stubMatchers { - jsonPath('$.email', byRegex(email())) - jsonPath('$.callback_url', byRegex(hostname())) + jsonPath('$.[\\'email\\']', byRegex(email())) + jsonPath('$.[\\'callback_url\\']', byRegex(hostname())) } } response { @@ -679,9 +679,9 @@ class DslToWireMockClientConverterSpec extends Specification { "url" : "/users/password2", "method" : "POST", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.email =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4})/)]" + "matchesJsonPath" : "$[?(@.['email'] =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4})/)]" }, { - "matchesJsonPath" : "$[?(@.callback_url =~ /(((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?)/)]" + "matchesJsonPath" : "$[?(@.['callback_url'] =~ /(((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?)/)]" } ], "headers" : { "Content-Type" : { diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy index 5b8a451115..65379af459 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy @@ -83,7 +83,7 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, property + "." + entry.key, entry.value) + processBodyElement(blockBuilder, property, property + "." + entry.key, entry.value) } @Override diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy index eaf1f3be42..dfa25d9124 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy @@ -103,7 +103,7 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, getMapKeyReferenceString(property, entry), entry.value) + processBodyElement(blockBuilder, property, getMapKeyReferenceString(property, entry), entry.value) } private String getMapKeyReferenceString(String property, Map.Entry entry) { diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy index 66099410b5..71506b2d9e 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy @@ -38,6 +38,7 @@ import org.springframework.cloud.contract.verifier.util.JsonPaths import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter import org.springframework.cloud.contract.verifier.util.MapConverter import org.springframework.util.SerializationUtils +import org.springframework.util.StringUtils import java.util.regex.Pattern @@ -331,7 +332,7 @@ abstract class MethodBodyBuilder { } } } - processBodyElement(bb, "", convertedResponseBody) + processBodyElement(bb, "", "", convertedResponseBody) } protected void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object copiedBody) { @@ -398,7 +399,7 @@ abstract class MethodBodyBuilder { // Doing a clone doesn't work for nested lists... private Object cloneBody(Object object) { - if (object instanceof List) { + if (object instanceof List || object instanceof Map) { byte[] serializedObject = SerializationUtils.serialize(object) return SerializationUtils.deserialize(serializedObject) } @@ -458,6 +459,21 @@ abstract class MethodBodyBuilder { return '"' + StringEscapeUtils.escapeJava(string) + '"' } + protected String trailingKey(String key) { + if (key.startsWith(".")) { + return key.substring(1) + } + return key + } + + private String wrappedWithBracketsForDottedProp(String key) { + String remindingKey = trailingKey(key) + if (remindingKey.contains(".")) { + return "['${remindingKey}']" + } + return remindingKey + } + /** * Post processing of each JSON path entry */ @@ -477,8 +493,8 @@ abstract class MethodBodyBuilder { * Appends to {@link BlockBuilder} processing of the given String value. */ protected void processText(BlockBuilder blockBuilder, String property, Object value) { - if (value instanceof String && value.startsWith('$')) { - String newValue = stripFirstChar(value).replaceAll('\\$value', "responseBody$property") + if (value instanceof String && (value as String).startsWith('$')) { + String newValue = stripFirstChar((value as String)).replaceAll('\\$value', "responseBody$property") blockBuilder.addLine(newValue) addColonIfRequired(blockBuilder) } else { @@ -502,6 +518,16 @@ abstract class MethodBodyBuilder { protected void processBodyElement(BlockBuilder blockBuilder, String property, Object value) { } + /** + * Appends to the {@link BlockBuilder} the assertion for the given body element + */ + protected void processBodyElement(BlockBuilder blockBuilder, String oldProp, String property, Object value) { + String propDiff = property - oldProp + String prop = wrappedWithBracketsForDottedProp(propDiff) + String mergedProp = StringUtils.hasText(property) ? "${oldProp}.${prop}" : "" + processBodyElement(blockBuilder, mergedProp, value) + } + /** * Removes unnecessary quotes */ @@ -589,7 +615,7 @@ abstract class MethodBodyBuilder { protected void processBodyElement(BlockBuilder blockBuilder, String property, List list) { list.eachWithIndex { listElement, listIndex -> String prop = getPropertyInListString(property, listIndex as Integer) - processBodyElement(blockBuilder, prop, listElement) + processBodyElement(blockBuilder, property, prop, listElement) } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy index c88ff2b094..b679c69b58 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy @@ -67,7 +67,7 @@ class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder { protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) { if (value instanceof NotToEscapePattern) { blockBuilder.addLine("assertThat(response.header(\"$property\"))." + - "${createMatchesMethod(value.serverValue.pattern().replace("\\", "\\\\"))};") + "${createMatchesMethod((value as NotToEscapePattern).serverValue.pattern().replace("\\", "\\\\"))};") } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy index c64726d68d..6c6a3041de 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy @@ -68,7 +68,7 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, property + "." + entry.key, entry.value) + processBodyElement(blockBuilder, property, property + "." + entry.key, entry.value) } @Override diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy index ea6a8b7130..94261e02ee 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy @@ -68,12 +68,12 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("parsedJson.read('\$$property')")}") + blockBuilder.addLine("${exec.insertValue("parsedJson.read('''\$$property''')")}") } @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, property + "." + entry.key, entry.value) + processBodyElement(blockBuilder, property, property + "." + entry.key, entry.value) } @Override diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java index 9fdaf5ce88..1bb87ded29 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java @@ -82,11 +82,12 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable field(Object value) { Object valueToPut = value instanceof ShouldTraverse ? ((ShouldTraverse) value).value : value; - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(valueToPut), this.methodsBuffer); + Object wrappedValue = wrapInBrackets(valueToPut); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(wrappedValue), this.methodsBuffer); if (this.delegate.isIteratingOverArray() && !(value instanceof ShouldTraverse)) { - verifiable.appendMethodWithQuotedValue("contains", wrapInBrackets(valueToPut)); + verifiable.appendMethodWithQuotedValue("contains", wrappedValue); } else { - verifiable.appendMethodWithQuotedValue("field", wrapInBrackets(valueToPut)); + verifiable.appendMethodWithQuotedValue("field", wrappedValue); } return verifiable; } @@ -102,15 +103,17 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable { @Override public MethodBufferingJsonVerifiable array(Object value) { - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(value), this.methodsBuffer); - verifiable.appendMethodWithQuotedValue("array", wrapInBrackets(value)); + Object valueToPut = wrapInBrackets(value); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(valueToPut), this.methodsBuffer); + verifiable.appendMethodWithQuotedValue("array", valueToPut); return verifiable; } @Override public MethodBufferingJsonVerifiable arrayField(Object value) { - DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(value).arrayField(), this.methodsBuffer); - verifiable.appendMethodWithQuotedValue("array", wrapInBrackets(value)); + Object valueToPut = wrapInBrackets(value); + DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(valueToPut).arrayField(), this.methodsBuffer); + verifiable.appendMethodWithQuotedValue("array", valueToPut); return verifiable; } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy index 6b31ae36dd..d980e6dbeb 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy @@ -113,13 +113,25 @@ class JsonToJsonPathsConverter { if (value == null && bodyMatcher.matchingType() != MatchingType.EQUALITY) { return path } - int lastIndexOfDot = path.lastIndexOf(".") + int lastIndexOfDot = lastIndexOfDot(path) String toLastDot = path.substring(0, lastIndexOfDot) String fromLastDot = path.substring(lastIndexOfDot + 1) String comparison = createComparison(bodyMatcher, value, body) return "${toLastDot}[?(@.${fromLastDot} ${comparison})]" } + private static int lastIndexOfDot(String path) { + if (pathContainsDotSeparatedKey(path)) { + int lastIndexOfBracket = path.lastIndexOf("['") + return path.substring(0, lastIndexOfBracket).lastIndexOf(".") + } + return path.lastIndexOf(".") + } + + private static boolean pathContainsDotSeparatedKey(String path) { + return path.contains("['") + } + private static String createComparison(BodyMatcher bodyMatcher, Object value, def body) { if (bodyMatcher.matchingType() == MatchingType.EQUALITY) { if (!body) { diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy index 454120961d..01109a0e46 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy @@ -16,6 +16,8 @@ package org.springframework.cloud.contract.verifier.builder +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.dsl.WireMockStubVerifier @@ -780,6 +782,20 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains('assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason.title"));') } + String sampleJson = ''' + + [ + { + "name" : "iPhone", + "number": "0123-4567-8888" + }, + { + "name" : "home", + "number": "0123-4567-8910" + } + ] +''' + @Issue('#85') def "should execute custom method for more complex structures on the response side when using Spock"() { given: @@ -806,8 +822,11 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[0].name")''') - test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[1].name")''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[0].name")''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[1].name")''') + and: + DocumentContext context = JsonPath.parse(sampleJson) + context.read('$.[0].name') == 'iPhone' } @Issue('#85') @@ -836,8 +855,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub builder.then(blockBuilder) def test = blockBuilder.toString() then: - test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[0].name")''') - test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[1].name")''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[0].name")''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[1].name")''') } @Issue('#150') diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy index f19160ccbf..26314cd5d6 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy @@ -83,7 +83,7 @@ class MethodBodyBuilderSpec extends Specification implements WireMockStubVerifie builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: - test.contains('$.myArray[0].anotherArrayNeededForBug[0].optionalNotEmpty') + test.contains('$.myArray.[0].anotherArrayNeededForBug.[0].optionalNotEmpty') !test.contains('cursor') !test.contains('REGEXP>>') and: @@ -106,4 +106,51 @@ DocumentContext parsedJson = JsonPath.parse(json); "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } } + @Issue('#269') + def "should work with execute and keys with dots [#methodBuilderName]"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + urlPath '/foo' + } + response { + status 200 + body ( + foo: ["my.dotted.response" : $(c('foo'), p(execute('"foo".equals($it)')))] + ) + headers { + contentType(applicationJson()) + } + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + test.contains('''$.foo.['my.dotted.response']''') + !test.contains('cursor') + !test.contains('REGEXP>>') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + and: + String jsonSample = '''\ +String json = "{\\"foo\\":{\\"my.dotted.response\\":\\"foo\\"}}"; +DocumentContext parsedJson = JsonPath.parse(json); +''' + and: + LinkedList lines = [] as LinkedList + test.eachLine { if (it.contains('"foo".equals')) lines << it else it } + lines.addFirst(jsonSample) + SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) + where: + methodBuilderName | methodBuilder + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } + "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } + "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } + } + } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy index 7c15e45f2f..6bd371e795 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy @@ -1022,7 +1022,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } where: methodBuilderName | methodBuilder | assertionStrings - "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | ['''assertThatRejectionReasonIsNull(parsedJson.read('$.rejectionReason'))''', '''assertThatLocationIsNull(response.header('Location'))'''] + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | ['''assertThatRejectionReasonIsNull(parsedJson.read(\'\'\'$.rejectionReason\'\'\'))''', '''assertThatLocationIsNull(response.header('Location'))'''] "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] } @@ -1690,7 +1690,7 @@ World.'''""" builder.then(blockBuilder) def test = blockBuilder.toString() then: - test.contains('assertThatRejectionReasonIsNull(parsedJson.read(\'$.rejectionReason.title\'))') + test.contains('assertThatRejectionReasonIsNull(parsedJson.read(\'\'\'$.rejectionReason.title\'\'\'))') when: SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) then: @@ -1724,8 +1724,8 @@ World.'''""" builder.then(blockBuilder) def test = blockBuilder.toString() then: - test.contains('''assertThatUserNameIsNotNull(parsedJson.read('$[0].name')''') - test.contains('''assertThatUserNameIsNotNull(parsedJson.read('$[1].name')''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read(\'\'\'$.[0].name\'\'\')''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read(\'\'\'$.[1].name\'\'\')''') } @Issue('#85') @@ -1754,8 +1754,8 @@ World.'''""" builder.then(blockBuilder) def test = blockBuilder.toString() then: - test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[0].name")''') - test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[1].name")''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[0].name")''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[1].name")''') } @Issue('#111') diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy index 222e6e76b7..ae0522819d 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy @@ -51,7 +51,10 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements dateTime: "2017-01-01T01:23:45", time: "01:02:34", valueWithoutAMatcher: "foo", - valueWithTypeMatch: "string" + valueWithTypeMatch: "string", + key: [ + 'complex.key' : 'foo' + ] ]) stubMatchers { jsonPath('$.duck', byRegex("[0-9]{3}")) @@ -63,6 +66,7 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements jsonPath('$.date', byDate()) jsonPath('$.dateTime', byTimestamp()) jsonPath('$.time', byTime()) + jsonPath("\$.['key'].['complex.key']", byEquality()) } headers { contentType(applicationJson()) @@ -91,6 +95,9 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements ], valueWithMinEmpty: [], valueWithMaxEmpty: [], + key: [ + 'complex.key' : 'foo' + ] ]) testMatchers { // asserts the jsonpath value against manual regex @@ -131,6 +138,7 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements }) // will execute a method `assertThatValueIsANumber` jsonPath('$.duck', byCommand('assertThatValueIsANumber($it)')) + jsonPath("\$.['key'].['complex.key']", byEquality()) } headers { contentType(applicationJson()) @@ -165,6 +173,7 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements test.contains('assertThat((Object) parsedJson.read("' + rootElement + '.valueWithMaxEmpty")).isInstanceOf(java.util.List.class)') test.contains('assertThat(parsedJson.read("' + rootElement + '.valueWithMaxEmpty", java.util.Collection.class).size()).isLessThanOrEqualTo(0)') test.contains('assertThatValueIsANumber(parsedJson.read("' + rootElement + '.duck")') + test.contains('assertThat(parsedJson.read("' + rootElement + '''.['key'].['complex.key']", String.class)).isEqualTo("foo")''') !test.contains('cursor') and: try { diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy index 1316aa4ad2..60a30700c4 100755 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy @@ -18,6 +18,7 @@ package org.springframework.cloud.contract.verifier.dsl import groovy.json.JsonBuilder import groovy.json.JsonSlurper +import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockStubStrategy import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.AssertionUtil @@ -257,7 +258,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "urlPattern" : "/[0-9]{2}", "method" : "GET", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.name == 'Jan')]" + "matchesJsonPath" : "$[?(@.['name'] == 'Jan')]" } ] }, "response" : { @@ -305,13 +306,13 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "urlPattern" : "/[0-9]{2}", "method" : "GET", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.created == '2014-02-02 12:23:43')]" + "matchesJsonPath" : "$[?(@.['created'] == '2014-02-02 12:23:43')]" }, { - "matchesJsonPath" : "$[?(@.surname =~ /[a-zA-Z]+/)]" + "matchesJsonPath" : "$[?(@.['surname'] =~ /[a-zA-Z]+/)]" }, { - "matchesJsonPath" : "$[?(@.name == 'Jan')]" + "matchesJsonPath" : "$[?(@.['name'] == 'Jan')]" }, { - "matchesJsonPath" : "$[?(@.id =~ /[0-9]+/)]" + "matchesJsonPath" : "$[?(@.['id'] =~ /[0-9]+/)]" } ] }, "response" : { @@ -351,7 +352,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "url" : "/users", "method" : "GET", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.name == 'Jan')]" + "matchesJsonPath" : "$[?(@.['name'] == 'Jan')]" } ], "headers" : { "Content-Type" : { @@ -589,7 +590,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "urlPattern" : "/[0-9]{2}", "method" : "GET", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.personalId =~ /^[0-9]{11}$/)]" + "matchesJsonPath" : "$[?(@.['personalId'] =~ /^[0-9]{11}$/)]" } ] }, "response" : { @@ -644,9 +645,9 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.loanAmount == 123.123)]" + "matchesJsonPath" : "$[?(@.['loanAmount'] == 123.123)]" }, { - "matchesJsonPath" : "$[?(@.clientPesel =~ /[0-9]{10}/)]" + "matchesJsonPath" : "$[?(@.['clientPesel'] =~ /[0-9]{10}/)]" } ], "headers" : { "Content-Type" : { @@ -1032,17 +1033,17 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "urlPattern" : "/[0-9]{2}", "method" : "GET", "bodyPatterns" : [ { - "matchesJsonPath" : "$.errors[*][?(@.propertyName =~ /[0-9]{2}/)]" + "matchesJsonPath" : "$.['errors'][*][?(@.['propertyName'] =~ /[0-9]{2}/)]" }, { - "matchesJsonPath" : "$.errors[*][?(@.providerValue == 'Test')]" + "matchesJsonPath" : "$.['errors'][*][?(@.['providerValue'] == 'Test')]" }, { - "matchesJsonPath" : "$[?(@.lastName =~ /.*/)]" + "matchesJsonPath" : "$[?(@.['lastName'] =~ /.*/)]" }, { - "matchesJsonPath" : "$[?(@.firstName =~ /.*/)]" + "matchesJsonPath" : "$[?(@.['firstName'] =~ /.*/)]" }, { - "matchesJsonPath" : "$[?(@.birthDate =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/)]" + "matchesJsonPath" : "$[?(@.['birthDate'] =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/)]" }, { - "matchesJsonPath" : "$[?(@.personalId =~ /[0-9]{11}/)]" + "matchesJsonPath" : "$[?(@.['personalId'] =~ /[0-9]{11}/)]" }] }, "response" : { @@ -1092,17 +1093,17 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "url" : "/reissue-payment-order", "method" : "POST", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.loanNumber == '999997001')]" + "matchesJsonPath" : "$[?(@.['loanNumber'] == '999997001')]" }, { - "matchesJsonPath" : "$[?(@.username =~ /.*/)]" + "matchesJsonPath" : "$[?(@.['username'] =~ /.*/)]" }, { - "matchesJsonPath" : "$[?(@.amount =~ /[0-9.]+/)]" + "matchesJsonPath" : "$[?(@.['amount'] =~ /[0-9.]+/)]" }, { - "matchesJsonPath" : "$[?(@.cardId == 1)]" + "matchesJsonPath" : "$[?(@.['cardId'] == 1)]" }, { - "matchesJsonPath" : "$[?(@.currency == 'DKK')]" + "matchesJsonPath" : "$[?(@.['currency'] == 'DKK')]" }, { - "matchesJsonPath" : "$[?(@.applicationName =~ /.*/)]" + "matchesJsonPath" : "$[?(@.['applicationName'] =~ /.*/)]" } ] }, "response" : { @@ -1201,7 +1202,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "request" : { "method" : "POST", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.property == 'value')]" + "matchesJsonPath" : "$[?(@.['property'] == 'value')]" } ] }, "response" : { @@ -1285,9 +1286,9 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "url" : "/users/password", "method" : "POST", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.callback_url =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]" + "matchesJsonPath" : "$[?(@.['callback_url'] =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]" }, { - "matchesJsonPath" : "$[?(@.email =~ /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}/)]" + "matchesJsonPath" : "$[?(@.['email'] =~ /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}/)]" } ], "headers" : { "Content-Type" : { @@ -1336,7 +1337,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "urlPattern" : "/partners/^[0-9]*$/agents/11/customers/09665703Z", "method" : "PUT", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.first_name == 'Josef')]" + "matchesJsonPath" : "$[?(@.['first_name'] == 'Josef')]" } ], "headers" : { "Content-Type" : { @@ -1364,9 +1365,9 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "url" : "/users/password", "method" : "POST", "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.callback_url =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]" + "matchesJsonPath" : "$[?(@.['callback_url'] =~ /((http[s]?|ftp):\\\\/)\\\\/?([^:\\\\/\\\\s]+)(:[0-9]{1,5})?/)]" }, { - "matchesJsonPath" : "$[?(@.email =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4})?/)]" + "matchesJsonPath" : "$[?(@.['email'] =~ /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4})?/)]" } ], "headers" : { "Content-Type" : { @@ -1632,4 +1633,53 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie then: json == '' } + + @Issue('#269') + def "should create a stub for dot separated keys"() { + given: + Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make { + request { + method 'PUT' + url '/fraudcheck' + body([ // (4) + "client.id": $(regex('[0-9]{10}')), + loanAmount: 99999 + ]) + headers { + contentType('application/vnd.fraud.v1+json') + } + } + response { + status 200 + } + } + when: + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + then: + AssertionUtil.assertThatJsonsAreEqual(''' + { + "request" : { + "url" : "/fraudcheck", + "method" : "PUT", + "headers" : { + "Content-Type" : { + "matches" : "application/vnd\\\\.fraud\\\\.v1\\\\+json.*" + } + }, + "bodyPatterns" : [ { + "matchesJsonPath" : "$[?(@.['loanAmount'] == 99999)]" + }, { + "matchesJsonPath" : "$[?(@.['client.id'] =~ /[0-9]{10}/)]" + } ] + } + }, + "response" : { + "status" : 200 + } + } + ''', wireMockStub) + and: + stubMappingIsValidWireMockStub(wireMockStub) + + } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy index e5a1bb2e5f..81594524cb 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverterSpec.groovy @@ -39,23 +39,23 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" && - it.jsonPath() == '''$[*].some.nested[?(@.json == 'with value')]''' + it.jsonPath() == '''$[*].['some'].['nested'][?(@.['json'] == 'with value')]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" && - it.jsonPath() == '''$[*].some.nested[?(@.anothervalue == 4)]''' + it.jsonPath() == '''$[*].['some'].['nested'][?(@.['anothervalue'] == 4)]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" && - it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name1')]''' + it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" && - it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name2')]''' + it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").field("['anothernested']").field("['name']").isEqualTo("name3")""" && - it.jsonPath() == '''$[*].some.nested.withlist[*].anothernested[?(@.name == 'name3')]''' + it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*].['anothernested'][?(@.['name'] == 'name3')]''' } and: assertThatJsonPathsInMapAreValid(json, pathAndValues) @@ -132,19 +132,19 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method() == """.field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" && - it.jsonPath() == '''$.some.nested[?(@.json == 'with value')]''' + it.jsonPath() == '''$.['some'].['nested'][?(@.['json'] == 'with value')]''' } pathAndValues.find { it.method() == """.field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" && - it.jsonPath() == '''$.some.nested[?(@.anothervalue == 4)]''' + it.jsonPath() == '''$.['some'].['nested'][?(@.['anothervalue'] == 4)]''' } pathAndValues.find { it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" && - it.jsonPath() == '''$.some.nested.withlist[*][?(@.name == 'name1')]''' + it.jsonPath() == '''$.['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]''' } pathAndValues.find { it.method() == """.field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" && - it.jsonPath() == '''$.some.nested.withlist[*][?(@.name == 'name2')]''' + it.jsonPath() == '''$.['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]''' } and: assertThatJsonPathsInMapAreValid(json, pathAndValues) @@ -162,7 +162,7 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method() == """.array("['items']").arrayField().isEqualTo("HOP").value()""" && - it.jsonPath() == '''$.items[?(@ == 'HOP')]''' + it.jsonPath() == '''$.['items'][?(@ == 'HOP')]''' } and: assertThatJsonPathsInMapAreValid(json, pathAndValues) @@ -181,11 +181,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method() == """.field("['property1']").isNull()""" && - it.jsonPath() == '''$[?(@.property1 == null)]''' + it.jsonPath() == '''$[?(@.['property1'] == null)]''' } pathAndValues.find { it.method() == """.field("['property2']").isEqualTo(true)""" && - it.jsonPath() == '''$[?(@.property2 == true)]''' + it.jsonPath() == '''$[?(@.['property2'] == true)]''' } } @@ -200,15 +200,15 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method() == """.field("['extensions']").field("['7']").isEqualTo(28.00)""" && - it.jsonPath() == '''$.extensions[?(@.7 == 28.00)]''' + it.jsonPath() == '''$.['extensions'][?(@.['7'] == 28.00)]''' } pathAndValues.find { it.method() == """.field("['extensions']").field("['14']").isEqualTo(41.00)""" && - it.jsonPath() == '''$.extensions[?(@.14 == 41.00)]''' + it.jsonPath() == '''$.['extensions'][?(@.['14'] == 41.00)]''' } pathAndValues.find { it.method() == """.field("['extensions']").field("['30']").isEqualTo(60.00)""" && - it.jsonPath() == '''$.extensions[?(@.30 == 60.00)]''' + it.jsonPath() == '''$.['extensions'][?(@.['30'] == 60.00)]''' } and: assertThatJsonPathsInMapAreValid(json, pathAndValues) @@ -229,15 +229,15 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method() == """.array("['errors']").contains("['property']").isEqualTo("email")""" && - it.jsonPath() == '''$.errors[*][?(@.property == 'email')]''' + it.jsonPath() == '''$.['errors'][*][?(@.['property'] == 'email')]''' } pathAndValues.find { it.method() == """.array("['errors']").contains("['message']").isEqualTo("inconsistent value")""" && - it.jsonPath() == '''$.errors[*][?(@.message == 'inconsistent value')]''' + it.jsonPath() == '''$.['errors'][*][?(@.['message'] == 'inconsistent value')]''' } pathAndValues.find { it.method() == """.array("['errors']").contains("['message']").isEqualTo("inconsistent value2")""" && - it.jsonPath() == '''$.errors[*][?(@.message == 'inconsistent value2')]''' + it.jsonPath() == '''$.['errors'][*][?(@.['message'] == 'inconsistent value2')]''' } and: assertThatJsonPathsInMapAreValid(json, pathAndValues) @@ -280,30 +280,30 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").field("['json']").isEqualTo("with value")""" && - it.jsonPath() == '''$[*].some.nested[?(@.json == 'with value')]''' + it.jsonPath() == '''$[*].['some'].['nested'][?(@.['json'] == 'with value')]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").field("['anothervalue']").isEqualTo(4)""" && - it.jsonPath() == '''$[*].some.nested[?(@.anothervalue == 4)]''' + it.jsonPath() == '''$[*].['some'].['nested'][?(@.['anothervalue'] == 4)]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name1")""" && - it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name1')]''' + it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name1')]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").contains("['name']").isEqualTo("name2")""" && - it.jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name2')]''' + it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*][?(@.['name'] == 'name2')]''' } pathAndValues.find { it.method() == """.array().field("['some']").field("['nested']").array("['withlist']").field("['anothernested']").field("['name']").matches("[a-zA-Z]+")""" && - it.jsonPath() == '''$[*].some.nested.withlist[*].anothernested[?(@.name =~ /[a-zA-Z]+/)]''' + it.jsonPath() == '''$[*].['some'].['nested'].['withlist'][*].['anothernested'][?(@.['name'] =~ /[a-zA-Z]+/)]''' } when: json.some.nested.withlist[0][2].anothernested.name = "Kowalski" then: assertThatJsonPathsInMapAreValid(JsonOutput.prettyPrint(JsonOutput.toJson(json)), pathAndValues) } - + def "should generate assertions for simple response body"() { given: @@ -316,11 +316,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property1']").isEqualTo("a")""" && - it.jsonPath() == """\$[?(@.property1 == 'a')]""" + it.jsonPath() == """\$[?(@.['property1'] == 'a')]""" } pathAndValues.find { it.method()== """.field("['property2']").isEqualTo("b")""" && - it.jsonPath() == """\$[?(@.property2 == 'b')]""" + it.jsonPath() == """\$[?(@.['property2'] == 'b')]""" } and: pathAndValues.size() == 2 @@ -338,15 +338,15 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property1']").isEqualTo("true")""" && - it.jsonPath() == """\$[?(@.property1 == 'true')]""" + it.jsonPath() == """\$[?(@.['property1'] == 'true')]""" } pathAndValues.find { it.method()== """.field("['property2']").isNull()""" && - it.jsonPath() == """\$[?(@.property2 == null)]""" + it.jsonPath() == """\$[?(@.['property2'] == null)]""" } pathAndValues.find { it.method()== """.field("['property3']").isEqualTo(false)""" && - it.jsonPath() == """\$[?(@.property3 == false)]""" + it.jsonPath() == """\$[?(@.['property3'] == false)]""" } and: pathAndValues.size() == 3 @@ -366,15 +366,15 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property1']").isEqualTo("a")""" && - it.jsonPath() == """\$[?(@.property1 == 'a')]""" + it.jsonPath() == """\$[?(@.['property1'] == 'a')]""" } pathAndValues.find { it.method()== """.array("['property2']").contains("['a']").isEqualTo("sth")""" && - it.jsonPath() == """\$.property2[*][?(@.a == 'sth')]""" + it.jsonPath() == """\$.['property2'][*][?(@.['a'] == 'sth')]""" } pathAndValues.find { it.method()== """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" && - it.jsonPath() == """\$.property2[*][?(@.b == 'sthElse')]""" + it.jsonPath() == """\$.['property2'][*][?(@.['b'] == 'sthElse')]""" } and: pathAndValues.size() == 3 @@ -396,19 +396,19 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property1']").isEqualTo("a")""" && - it.jsonPath() == """\$[?(@.property1 == 'a')]""" + it.jsonPath() == """\$[?(@.['property1'] == 'a')]""" } pathAndValues.find { it.method()== """.array("['property2']").contains("['a']").isEqualTo("sth")""" && - it.jsonPath() == """\$.property2[*][?(@.a == 'sth')]""" + it.jsonPath() == """\$.['property2'][*][?(@.['a'] == 'sth')]""" } pathAndValues.find { it.method()== """.array("['property2']").hasSize(2)""" && - it.jsonPath() == """\$.property2[*]""" + it.jsonPath() == """\$.['property2'][*]""" } pathAndValues.find { it.method()== """.array("['property2']").contains("['b']").isEqualTo("sthElse")""" && - it.jsonPath() == """\$.property2[*][?(@.b == 'sthElse')]""" + it.jsonPath() == """\$.['property2'][*][?(@.['b'] == 'sthElse')]""" } and: pathAndValues.size() == 4 @@ -427,11 +427,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property']").field(7).isEqualTo(0.0)""" && - it.jsonPath() == """\$.property[?(@.7 == 0.0)]""" + it.jsonPath() == """\$.['property'][?(@.7 == 0.0)]""" } pathAndValues.find { it.method()== """.field("['property']").field(14).isEqualTo(0.0)""" && - it.jsonPath() == """\$.property[?(@.14 == 0.0)]""" + it.jsonPath() == """\$.['property'][?(@.14 == 0.0)]""" } and: pathAndValues.size() == 2 @@ -451,11 +451,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array().contains("['property1']").isEqualTo("a")""" && - it.jsonPath() == """\$[*][?(@.property1 == 'a')]""" + it.jsonPath() == """\$[*][?(@.['property1'] == 'a')]""" } pathAndValues.find { it.method()== """.array().contains("['property2']").isEqualTo("b")""" && - it.jsonPath() == """\$[*][?(@.property2 == 'b')]""" + it.jsonPath() == """\$[*][?(@.['property2'] == 'b')]""" } and: pathAndValues.size() == 2 @@ -477,11 +477,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array().contains("['property1']").isEqualTo("a")""" && - it.jsonPath() == """\$[*][?(@.property1 == 'a')]""" + it.jsonPath() == """\$[*][?(@.['property1'] == 'a')]""" } pathAndValues.find { it.method()== """.array().contains("['property2']").isEqualTo("b")""" && - it.jsonPath() == """\$[*][?(@.property2 == 'b')]""" + it.jsonPath() == """\$[*][?(@.['property2'] == 'b')]""" } pathAndValues.find { it.method()== """.hasSize(2)""" && @@ -504,11 +504,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array("['property1']").contains("['property2']").isEqualTo("test1")""" && - it.jsonPath() == """\$.property1[*][?(@.property2 == 'test1')]""" + it.jsonPath() == """\$.['property1'][*][?(@.['property2'] == 'test1')]""" } pathAndValues.find { it.method()== """.array("['property1']").contains("['property3']").isEqualTo("test2")""" && - it.jsonPath() == """\$.property1[*][?(@.property3 == 'test2')]""" + it.jsonPath() == """\$.['property1'][*][?(@.['property3'] == 'test2')]""" } and: pathAndValues.size() == 2 @@ -529,15 +529,15 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array("['property1']").contains("['property2']").isEqualTo("test1")""" && - it.jsonPath() == """\$.property1[*][?(@.property2 == 'test1')]""" + it.jsonPath() == """\$.['property1'][*][?(@.['property2'] == 'test1')]""" } pathAndValues.find { it.method()== """.array("['property1']").contains("['property3']").isEqualTo("test2")""" && - it.jsonPath() == """\$.property1[*][?(@.property3 == 'test2')]""" + it.jsonPath() == """\$.['property1'][*][?(@.['property3'] == 'test2')]""" } pathAndValues.find { it.method()== """.array("['property1']").hasSize(2)""" && - it.jsonPath() == """\$.property1[*]""" + it.jsonPath() == """\$.['property1'][*]""" } and: pathAndValues.size() == 3 @@ -554,11 +554,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property2']").field("['property3']").isEqualTo("b")""" && - it.jsonPath() == """\$.property2[?(@.property3 == 'b')]""" + it.jsonPath() == """\$.['property2'][?(@.['property3'] == 'b')]""" } pathAndValues.find { it.method()== """.field("['property1']").isEqualTo("a")""" && - it.jsonPath() == """\$[?(@.property1 == 'a')]""" + it.jsonPath() == """\$[?(@.['property1'] == 'a')]""" } and: pathAndValues.size() == 2 @@ -575,11 +575,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property2']").matches("[0-9]{3}")""" && - it.jsonPath() == """\$[?(@.property2 =~ /[0-9]{3}/)]""" + it.jsonPath() == """\$[?(@.['property2'] =~ /[0-9]{3}/)]""" } pathAndValues.find { it.method()== """.field("['property1']").isEqualTo("a")""" && - it.jsonPath() == """\$[?(@.property1 == 'a')]""" + it.jsonPath() == """\$[?(@.['property1'] == 'a')]""" } and: pathAndValues.size() == 2 @@ -595,7 +595,7 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.field("['property2']").matches("\\\\d+")""" && - it.jsonPath() == """\$[?(@.property2 =~ /\\d+/)]""" + it.jsonPath() == """\$[?(@.['property2'] =~ /\\d+/)]""" } and: pathAndValues.size() == 1 @@ -614,11 +614,11 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" && - it.jsonPath() == """\$.errors[*][?(@.property == 'bank_account_number')]""" + it.jsonPath() == """\$.['errors'][*][?(@.['property'] == 'bank_account_number')]""" } pathAndValues.find { it.method()== """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" && - it.jsonPath() == """\$.errors[*][?(@.message == 'incorrect_format')]""" + it.jsonPath() == """\$.['errors'][*][?(@.['message'] == 'incorrect_format')]""" } and: pathAndValues.size() == 2 @@ -639,15 +639,15 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array("['errors']").contains("['property']").isEqualTo("bank_account_number")""" && - it.jsonPath() == """\$.errors[*][?(@.property == 'bank_account_number')]""" + it.jsonPath() == """\$.['errors'][*][?(@.['property'] == 'bank_account_number')]""" } pathAndValues.find { it.method()== """.array("['errors']").contains("['message']").isEqualTo("incorrect_format")""" && - it.jsonPath() == """\$.errors[*][?(@.message == 'incorrect_format')]""" + it.jsonPath() == """\$.['errors'][*][?(@.['message'] == 'incorrect_format')]""" } pathAndValues.find { it.method()== """.array("['errors']").hasSize(1)""" && - it.jsonPath() == """\$.errors[*]""" + it.jsonPath() == """\$.['errors'][*]""" } and: pathAndValues.size() == 3 @@ -675,19 +675,19 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.995548)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.995548)]""" } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-77.119759)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -77.119759)]""" } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-76.909393)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -76.909393)]""" } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.791645)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.791645)]""" } and: pathAndValues.size() == 4 @@ -721,19 +721,19 @@ class JsonToJsonPathsConverterSpec extends Specification { then: pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.995548)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.995548)]""" } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-77.119759)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -77.119759)]""" } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(-76.909393)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == -76.909393)]""" } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().arrayField().isEqualTo(38.791645)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*][?(@ == 38.791645)]""" } pathAndValues.find { it.method()== """.hasSize(1)""" && @@ -741,11 +741,11 @@ class JsonToJsonPathsConverterSpec extends Specification { } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").array().hasSize(2)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*][*]""" } pathAndValues.find { it.method()== """.array().field("['place']").field("['bounding_box']").array("['coordinates']").hasSize(1)""" && - it.jsonPath() == """\$[*].place.bounding_box.coordinates[*]""" + it.jsonPath() == """\$[*].['place'].['bounding_box'].['coordinates'][*]""" } and: pathAndValues.size() == 7 @@ -780,6 +780,15 @@ class JsonToJsonPathsConverterSpec extends Specification { '$.a.b.c[?(@.d == 1234)]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, null), body) } + def "should convert a json path with value to a equality checking for a key with dots"() { + given: + String jsonPath = '$.a.b.c.[\'d.e\']' + and: + def body = [ a: [ b: [ c: [ "d.e" : 1234 ] ] ] ] + expect: + '$.a.b.c[?(@.[\'d.e\'] == 1234)]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, null), body) + } + def "should convert a json path with value to a equality checking json path with quotes for strings"() { given: String jsonPath = '$.a.b.c.d'