Is there a way to implement the Postgres equivalent to CHECK constraint within a nested JSON Schema? Say we have data that has two properties, each of which has nested properties. How can JSON Schema make the required contents of the first object depend on the second?
My real case scenario is to build a JSON schema for a GeoJSON objects, that has a geometry object (i.e. Point or Polygon, or null), and other attributes in a "properties" object. I want to alter the required properties depending on the type of geometry.
I failed with both the following solutions:
- Nest "allOf" inside "anyOf" to cover all the possibilities
- Duplicate the "definitions" to have a attributes_no_geom, geometry_no_geom, attribute_with_geom and geometry_with_geom and declare them in a "anyOf"
This would validate since attribute/place covers for the lack of geometry:
{
"attributes": {
"name": "Person2",
"place": "City2"
},
"geometry": null
}
This would also validate since attribute/place is no longer required with a geometry:
{
"attributes": {
"name": "Person1"
},
"geometry": {
"type": "Point",
"coordinates": []
}
}
EDIT
Building on Relequestual's answer, this is the unsatisfactory result I'm getting :
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"geometryIsPoint": {
"type": "object",
"required": ["type"],
"properties": {
"type": {
"const": "Point"
}
}
},
"partialAttributes": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
},
"place": {
"type": "string"
}
}
},
"fullAttributes": {
"type": "object",
"required": ["name", "place"],
"properties": {
"name": {
"type": "string"
},
"place": {
"type": "string"
}
}
},
"conditionalAttributes": {
"allOf": [
{
"if": {
"$ref": "#/definitions/geometryIsPoint"
},
"then": {
"$ref": "#/definitions/partialAttributes"
},
"else": {
"$ref": "#/definitions/fullAttributes"
}
}
]
}
},
"properties": {
"attributes": {
"$ref": "#/definitions/conditionalAttributes"
},
"geometry": {
"$ref": "#/definitions/geometryIsPoint"
}
}
}
This schema will not validate the following if the attributes/place
property is removed.
{
"attributes": {
"name": "Person",
"place": "INVALID IF THIS LINE IS REMOVED ;-("
},
"geometry": {
"type": "Point",
"coordinates": {}
}
}
if/then/else
keywords, wrapped inside anallOf
to achive what you want here. I hope to provide you with a fuller answer sometime today. – Relequestualif geometry/type then require something in attributes
? – Lecram