I'm building a schema in which I have an array of items to be added. Each item represents an entity containing data and some metadata (configuration values) attached.
The metadata is almost always identical for each entity, so my plan is to put the metadata as a common top-level object in the schema. Then within the list of entities I'll have a schema for the actual data itself.
Very occasionally, it's useful to add an override where an entity can redefine a value from the metadata, specific to itself. That means I have to basically duplicate the metadata schema within each entity.
However, in that duplication, the only thing that will change is the required
ness (Properties that are required in the base need not be required in the overrides, since they've already been required in the base).
Here's an example of the setup that I'm implementing:
{
"type": "object",
"properties": {
"metadata": {
"title": "Base metadata values",
"description": "The base values which most of the array of entities will use (you only want to fill them in once).",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"height": {
"type": "number"
}
},
"required": [
"name",
"height"
]
},
"entities": {
"title": "Array of entities",
"type": "array",
"items": {
"title": "An entity",
"type": "object",
"properties": {
"data": {
"type": "string",
"description": "actual data associated with each entity"
},
"metadata_overrides": {
"title": "Override base metadata values",
"description": "Most entities will use the common base values, but each entity could override one or more values. So this object needs to have the same schema as the met, EXCEPT that required fields are no longer required. Is it possible to take the baseField definition then compose it with a different \"required\" property, to avoid duplicating that part of the schema??.",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"height": {
"type": "number"
}
},
"required": []
}
}
}
}
}
}
If the only difference between properties.metadata
and properties.entities.items.properties.metadata_overrides
is the value of required
, is it possible to extract that subschema into a definition, but then compose it in some way, so that I can use definitions instead of repeating subschema everywhere?
Inspired by this answer I tried this:
{
"type": "object",
"properties": {
"metadata": {
"$ref": "#/definitions/metadata"
},
"entities": {
"title": "Array of entities",
"type": "array",
"items": {
"title": "An entity",
"type": "object",
"properties": {
"data": {
"type": "string",
"description": "actual data associated with each entity"
},
"metadata_overrides": {
"allOf": [
{
"$ref": "#/definitions/metadata"
}
],
"description": "This description *does* successfully override but the `required` property below doesn't",
"required": []
}
}
}
}
},
"definitions": {
"metadata": {
"title": "Metadata values",
"description": "Values which most of the array of entities will use (you only want to fill them in once).",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"height": {
"type": "number"
}
},
"required": [
"name",
"height"
]
}
}
}
But this produces a validation error for the following data, which should pass:
{
"entities": [
{
"metadata_overrides": {
"name": "Dodger"
}
}
],
"metadata": {
"name": "Artful",
"height": 10
}
}