So I have the following JSON structure:
{
"attributeA": "...",
"attributeB": "...",
"attributeC": "...",
"attributeD": "...",
"innerObjA": {
"attributeA": "...",
"attributeB": "...",
"attributeC": "...",
"exclusiveFieldX": "...",
},
"innerObjB": {
"attributeA": "...",
"attributeB": "...",
"attributeC": "...",
"exclusiveFieldY": "..."
}
}
and I am trying to build up a JSON Schema to validate the structure.
As of now I have something like this:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "A product in the catalog",
"type": "object",
"properties": {
"attributeA": {
"type": "String"
},
"attributeB": {
"type": "String"
},
"attributeC": {
"type": "String"
},
"attributeD": {
"type": "String"
},
"innerObjA": {
"type": "object",
"properties": {
"attributeA": {
"type": "String"
},
"attributeB": {
"type": "String"
},
"attributeC": {
"type": "String"
},
"exclusiveFieldX": {
"type": "String"
}
}
},
"innerObjB": {
"type": "object",
"properties": {
"attributeA": {
"type": "String"
},
"attributeB": {
"type": "String"
},
"attributeC": {
"type": "String"
},
"exclusiveFieldY": {
"type": "String"
}
}
}
},
"$defs": {
"common_inner_fields": {}
}
}
and I believe the “common_inner_fields” can be used to store the 3 common fields like this:
"$defs": {
"base_properties_platform": {
"attributeA": {
"type": "String"
},
"attributeB": {
"type": "String"
},
"attributeC": {
"type": "String"
}
}
}
but I don’t know if it’s possible to sort of combine that with the exclusive fields:
"innerObjA": {
"type": "object",
"properties": {
"$ref": "#/$defs/base_properties_platform",
"exclusiveFieldX": {
"type": "String"
}
}
},
"innerObjB": {
"type": "object",
"properties": {
"$ref": "#/$defs/base_properties_platform",
"exclusiveFieldY": {
"type": "String"
}
}
}
How can I achieve such combination?
John Doe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
You’re on the right track, one thing you need to consider is the draft version of JSON Schema being used. Some of the behavior changed over time.
I see your example is using draft2020-12, so I’ll focus on that one but provide earlier behavior for completeness
JSON Schema draft-2020-12
$ref
s can have sibling definitions at any level, so it’s just a matter of defining the $ref
and the additional properties
definition.
In your example, you have the $ref
inside the properties
definition, it should be a sibling to properties
.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "A product in the catalog",
"$ref": "#/$defs/base_properties_platform",
"type": "object",
"properties": {
"attributeD": {
"type": "string"
},
"innerObjA": {
"$ref": "#/$defs/base_properties_platform",
"type": "object",
"properties": {
"exclusiveFieldX": {
"type": "string"
}
}
},
"innerObjB": {
"$ref": "#/$defs/base_properties_platform",
"type": "object",
"properties": {
"exclusiveFieldY": {
"type": "string"
}
}
}
},
"$defs": {
"base_properties_platform": {
"attributeA": {
"type": "string"
},
"attributeB": {
"type": "string"
},
"attributeC": {
"type": "string"
}
}
}
}
JSON Schema draft-04 – present
The previous drafts required the use of allOf
to encapsulate the $ref
and properties
definition because prior to draft-2020-12, siblings were not allowed with $ref
. The spec remains backwards compatible to use this design if you are migrating from older versions.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "A product in the catalog",
"allOf": [
{
"$ref": "#/definitions/base_properties_platform"
},
{
"type": "object",
"properties": {
"attributeD": {
"type": "string"
},
"innerObjA": {
"allOf": [
{
"$ref": "#/definitions/base_properties_platform"
},
{
"type": "object",
"properties": {
"exclusiveFieldX": {
"type": "string"
}
}
}
]
},
"innerObjB": {
"allOf": [
{
"$ref": "#/definitions/base_properties_platform"
},
{
"type": "object",
"properties": {
"exclusiveFieldY": {
"type": "string"
}
}
}
]
}
}
}
],
"definitions": {
"base_properties_platform": {
"attributeA": {
"type": "string"
},
"attributeB": {
"type": "string"
},
"attributeC": {
"type": "string"
}
}
}
}
p.s. JSON Schema primitive types are always lowercase. string, object, array, number, integer, boolean, null