diff --git a/docs/pom.xml b/docs/pom.xml
index 91aa75acf6..667afba308 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -14,6 +14,7 @@
Spring Cloud Contract Docs
Spring Cloud Docs
+ 2.10.0
spring-cloud-contract
${basedir}/..
3.4
@@ -29,6 +30,40 @@
true
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ schema-test-compilation
+ generate-test-resources
+
+ testCompile
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ schema-generation
+ generate-test-resources
+
+ test
+
+
+
+ **/*Tests.*
+ **/*Test.*
+
+ plain
+ true
+
+
+
+
@@ -40,6 +75,12 @@
${project.groupId}
spring-cloud-starter-contract-verifier
+
+ com.fasterxml.jackson.module
+ jackson-module-jsonSchema
+ ${jackson-module-jsonSchema.version}
+ test
+
diff --git a/docs/src/main/asciidoc/_project-features-contract.adoc b/docs/src/main/asciidoc/_project-features-contract.adoc
index 02e05b300c..85daf731d5 100644
--- a/docs/src/main/asciidoc/_project-features-contract.adoc
+++ b/docs/src/main/asciidoc/_project-features-contract.adoc
@@ -164,6 +164,11 @@ IMPORTANT: Remember that, inside the Kotlin Script file, you have to provide the
Generally you would use its contract function like this: `org.springframework.cloud.contract.spec.ContractDsl.contract { ... }`.
You can also provide an import to the `contract` function (`import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract`) and then call `contract { ... }`.
+[[contract-yml]]
+=== Contract DSL in YML
+
+In order to see a schema of a YAML contract, you can check out the link:yml-schema.html[YML Schema] page.
+
[[contract-limitations]]
=== Limitations
diff --git a/docs/src/main/asciidoc/yml-schema.adoc b/docs/src/main/asciidoc/yml-schema.adoc
new file mode 100644
index 0000000000..0bae1f161d
--- /dev/null
+++ b/docs/src/main/asciidoc/yml-schema.adoc
@@ -0,0 +1,12 @@
+[[yml-schema]]
+== YML Schema
+include::_attributes.adoc[]
+
+Below you can find a JSON schema definition of a YAML contract.
+
+====
+[source,json,indent=0]
+----
+include::{project-root}/docs/target/contract_schema.json[indent=0]
+----
+====
diff --git a/docs/src/test/java/org/springframework/cloud/contract/docs/JsonSchemaTests.java b/docs/src/test/java/org/springframework/cloud/contract/docs/JsonSchemaTests.java
new file mode 100644
index 0000000000..49b16e2192
--- /dev/null
+++ b/docs/src/test/java/org/springframework/cloud/contract/docs/JsonSchemaTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.contract.docs;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Collection;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
+import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;
+import org.assertj.core.api.BDDAssertions;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.cloud.contract.spec.Contract;
+import org.springframework.cloud.contract.verifier.converter.YamlContract;
+import org.springframework.cloud.contract.verifier.converter.YamlContractConverter;
+
+class JsonSchemaTests {
+
+ // @formatter:off
+ private static final String CONTRACT = "description: Some description\n"
+ + "name: some name\n"
+ + "priority: 8\n"
+ + "ignored: true\n"
+ + "inProgress: true\n"
+ + "request:\n"
+ + " method: PUT\n"
+ + " url: /foo\n"
+ + " queryParameters:\n"
+ + " a: b\n"
+ + " b: c\n"
+ + " headers:\n"
+ + " foo: bar\n"
+ + " fooReq: baz\n"
+ + " cookies:\n"
+ + " foo: bar\n"
+ + " fooReq: baz\n"
+ + " body:\n"
+ + " foo: bar\n"
+ + " matchers:\n"
+ + " body:\n"
+ + " - path: $.foo\n"
+ + " type: by_regex\n"
+ + " value: bar\n"
+ + " headers:\n"
+ + " - key: foo\n"
+ + " regex: bar\n"
+ + "response:\n"
+ + " status: 200\n"
+ + " fixedDelayMilliseconds: 1000\n"
+ + " headers:\n"
+ + " foo2: bar\n"
+ + " foo3: foo33\n"
+ + " fooRes: baz\n"
+ + " body:\n"
+ + " foo2: bar\n"
+ + " foo3: baz\n"
+ + " nullValue: null\n"
+ + " matchers:\n"
+ + " body:\n"
+ + " - path: $.foo2\n"
+ + " type: by_regex\n"
+ + " value: bar\n"
+ + " - path: $.foo3\n"
+ + " type: by_command\n"
+ + " value: executeMe($it)\n"
+ + " - path: $.nullValue\n"
+ + " type: by_null\n"
+ + " value: null\n"
+ + " headers:\n"
+ + " - key: foo2\n"
+ + " regex: bar\n"
+ + " - key: foo3\n"
+ + " command: andMeToo($it)\n"
+ + " cookies:\n"
+ + " - key: foo2\n"
+ + " regex: bar\n"
+ + " - key: foo3\n"
+ + " predefined:\n";
+ // @formatter:on
+
+ @Test
+ void should_produce_a_json_schema_of_a_yaml_model() throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
+ JsonSchema schema = schemaGen.generateSchema(YamlContract.class);
+ String schemaString = mapper.writeValueAsString(schema);
+ File schemaFile = new File("target/contract_schema.json");
+ Files.write(schemaFile.toPath(), schemaString.getBytes());
+ }
+
+ @Test
+ void should_convert_yaml_to_contract() throws IOException {
+ File ymlFile = new File("target/contract.yml");
+ Files.write(ymlFile.toPath(), CONTRACT.getBytes());
+
+ Collection contracts = new YamlContractConverter().convertFrom(ymlFile);
+
+ BDDAssertions.then(contracts).isNotEmpty();
+ }
+
+}
diff --git a/docs/src/test/resources/contract.yml b/docs/src/test/resources/contract.yml
new file mode 100644
index 0000000000..5322f630b8
--- /dev/null
+++ b/docs/src/test/resources/contract.yml
@@ -0,0 +1,59 @@
+description: Some description
+name: some name
+priority: 8
+ignored: true
+inProgress: true
+request:
+ method: PUT
+ url: /foo
+ queryParameters:
+ a: b
+ b: c
+ headers:
+ foo: bar
+ fooReq: baz
+ cookies:
+ foo: bar
+ fooReq: baz
+ body:
+ foo: bar
+ matchers:
+ body:
+ - path: $.foo
+ type: by_regex
+ value: bar
+ headers:
+ - key: foo
+ regex: bar
+response:
+ status: 200
+ fixedDelayMilliseconds: 1000
+ headers:
+ foo2: bar
+ foo3: foo33
+ fooRes: baz
+ body:
+ foo2: bar
+ foo3: baz
+ nullValue: null
+ matchers:
+ body:
+ - path: $.foo2
+ type: by_regex
+ value: bar
+ - path: $.foo3
+ type: by_command
+ value: executeMe($it)
+ - path: $.nullValue
+ type: by_null
+ value: null
+ headers:
+ - key: foo2
+ regex: bar
+ - key: foo3
+ command: andMeToo($it)
+ cookies:
+ - key: foo2
+ regex: bar
+ - key: foo3
+ predefined: