JSON Schema for the enterprise
This document presents the Consumer Driven Contracts❐ sample application.
1 Consumer Driven Contracts
2 Contributing
3 Special Thanks
4 License
The JSONx Framework was created specifically for Consumer Driven Contracts❐. With the JSON Schema Definition Language (JSD), one can create a Consumer Driven Contract (CDC) with an evolution model based on schema versioning. The JSD can be used by producers and consumers to validate documents in a communication protocol.
The following example illustrates a simple protocol that uses the Consumer Driven Contracts❐ approach, and consists of the actors:
- Producer: Representing the provider of the ProductSearch service.
- Consumer1: The first consumer of the ProductSearch service.
- Consumer2: The second consumer of the ProductSearch service.
Consider a simple ProductSearch service, which allows consumer applications to search a product catalogue.
Version v1 of the protocol defines the contract:
-
Request
GET /ProductSearch?name=<name>
-
Response
{ "Version": "v1", "CatalogueID": <number>, "Name": <string>, "Price": <string>, "Manufacturer": <string>, "InStock": <boolean> }
The schema that describes the Response contract is:
{
"jx:ns": "http://www.jsonx.org/schema-0.3.jsd",
"jx:schemaLocation": "http://www.jsonx.org/schema-0.3.jsd http://www.jsonx.org/schema.jsd",
"product": { "jx:type": "object", "abstract": true, "properties": {
"CatalogueID": { "jx:type": "number", "range": "[1,]", "scale": 0, "nullable": false},
"Name": { "jx:type": "string", "pattern": "\\S|\\S.*\\S", "nullable": false },
"Price": { "jx:type": "string", "pattern": "\\$\\d+\\.\\d{2}", "nullable": false },
"Manufacturer": { "jx:type": "string", "pattern": "\\S|\\S.*\\S", "nullable": false },
"InStock": { "jx:type": "boolean", "nullable": false} } },
"product1": { "jx:type": "object", "extends": "product", "properties": {
"Version": { "jx:type": "string", "pattern": "v1", "nullable": false } } }
}
<schema
xmlns="http://www.jsonx.org/schema-0.3.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jsonx.org/schema-0.3.xsd http://www.jsonx.org/schema.xsd">
<object name="product" abstract="true">
<property name="CatalogueID" xsi:type="number" range="[1,]" scale="0" nullable="false"/>
<property name="Name" xsi:type="string" pattern="\S|\S.*\S" nullable="false"/>
<property name="Price" xsi:type="string" pattern="\$\d+\.\d{2}" nullable="false"/>
<property name="Manufacturer" xsi:type="string" pattern="\S|\S.*\S" nullable="false"/>
<property name="InStock" xsi:type="boolean" nullable="false"/>
</object>
<object name="product1" extends="product">
<property name="Version" xsi:type="string" pattern="v1" nullable="false"/>
</object>
</schema>
Note: The Converter utility automatically converts between JSD and JSDx.
All actors -- Producer, Consumer1, and Consumer2 -- agree on the contract, and implement and integrate the protocol into their systems. To assert receipt of contract-compliant documents, all actors use the contract definition to automatically validate received and sent messages.
After many months of running in production, Consumer2 issues a request to the Producer to provide additional information in the response. Specifically, Consumer2 requests for the addition of another field in the JSON response:
{
- "Version": "v1.0",
+ "Version": "v2.0",
"CatalogueID": <number>,
"Name": <string>,
"Price": <string>,
"Manufacturer": <string>,
"InStock": <boolean>,
+ "Description": <string>
}
To satisfy Consumer2's request, the contract is updated to support version v2 of the Response:
{
"jx:ns": "http://www.jsonx.org/schema-0.3.jsd",
"jx:schemaLocation": "http://www.jsonx.org/schema-0.3.jsd http://www.jsonx.org/schema.jsd",
"product": { "jx:type": "object", "abstract": true, "properties": {
"CatalogueID": { "jx:type": "number", "range": "[1,]", "scale": 0, "nullable": false},
"Name": { "jx:type": "string", "pattern": "\\S|\\S.*\\S", "nullable": false },
"Price": { "jx:type": "string", "pattern": "\\$\\d+\\.\\d{2}", "nullable": false },
"Manufacturer": { "jx:type": "string", "pattern": "\\S|\\S.*\\S", "nullable": false },
"InStock": { "jx:type": "boolean", "nullable": false} } },
"product1": { "jx:type": "object", "extends": "product", "properties": {
"Version": { "jx:type": "string", "pattern": "v1", "nullable": false } } }
+ "product2": { "jx:type": "object", "extends": "product", "properties": {
+ "Version": { "jx:type": "string", "pattern": "v2", "nullable": false },
+ "Description": { "jx:type": "string", "pattern": "\\S|\\S.*\\S", "nullable": false } } }
}
<schema
xmlns="http://www.jsonx.org/schema-0.3.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jsonx.org/schema-0.3.xsd http://www.jsonx.org/schema.xsd">
<object name="product" abstract="true">
<property name="CatalogueID" xsi:type="number" range="[1,]" scale="0" nullable="false"/>
<property name="Name" xsi:type="string" pattern="\S|\S.*\S" nullable="false"/>
<property name="Price" xsi:type="string" pattern="\$\d+\.\d{2}" nullable="false"/>
<property name="Manufacturer" xsi:type="string" pattern="\S|\S.*\S" nullable="false"/>
<property name="InStock" xsi:type="boolean" nullable="false"/>
</object>
<object name="product1" extends="product">
<property name="Version" xsi:type="string" pattern="v1" nullable="false"/>
</object>
+ <object name="product2" extends="product">
+ <property name="Version" xsi:type="string" pattern="v2" nullable="false"/>
+ <property name="Description" xsi:type="string" pattern="\S|\S.*\S" nullable="false"/>
+ </object>
</schema>
Note: The Converter utility automatically converts between JSD and JSDx.
With this approach, the v2 evolution of the contract satisfies Customer2. And, since the contract also retains support for v1, integration with Customer1 is unaffected.
The code included in this module implements this example.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
Special thanks to EJ Technologies for providing their award winning Java Profiler (JProfiler) for development of the JSONx Framework.
This project is licensed under the MIT License - see the LICENSE.txt file for details.