There's a few keywords you want to pay attention to, and likely refer to the specification for:
First, "type" allows multiple values to be specified in an array. With this you can specify e.g. ["string", "number"]
to mean "string or number." Many keywords only apply when the instance is of a certain JSON type. As a rule, you can combine a schema of one "type" and another with a different "type", if all the remaining keywords apply only to the respective types.
So as an example, you can have two schemas like:
{
"type": "string",
"minLength": 1
}
{
"type": "number",
"minimum": 0
}
And because "minimum" only applies to numbers, and "minLength" only applies to strings, you can simply combine the schemas together, and it will have the same effect:
{
"type": ["string", "number"],
"minLength": 1
"minimum": 0
}
However, with two schemas of the same "type", doing this will perform an intersection instead of a union. This is because adding keywords to a JSON Schema adds constraints, whereas adding values to the "type" list removes constraints (more values become valid).
So if you are performing a union over two schemas of the same "type", or if you are combining schemas with keywords that validate across all types (particularly "enum" or "const"), you will need to combine them with the "anyOf" keyword, which performs a union on an array of multiple schemas. (You may also consider "oneOf".)
I think you wind up with a schema like this:
{
"type": "object",
"properties": {
"idle_session_timeout": {
"type": ["number","string"],
"anyOf": [ {"type":"number"}, {"const":"none"} ]
},
"item": {
"type": "object",
"required": ["kind", "name"],
"properties": {
"kind": { "type": "string" },
"name": { "type": "string" },
},
"anyOf": [
{
"properties": {
"kind": { "const": "attribute" },
}
},
{
"properties": {
"kind": { "const": "relation" },
}
},
{
"required": ["entries"],
"properties": {
"kind": { "const": "group" },
"label": { "type": "string" },
"entries": { "type":"array", "items": {"$ref":"PresentationItem"} },
}
}
]
},
"order_by": {
"type": ["string", "object"],
"required": ["attribute"],
"properties": {
"attribute": { "type": "string" },
"direction": { "enum": ["asc", "desc"] },
}
}
}
Notice how I've factored out common keywords out of "anyOf" into the highest level possible. This is a stylistic choice. It produces slightly cleaner errors, but it might not be relevant for you depending on how you plan on growing the schema.
anyOf
should be what you’re looking for. For simple enums like in theorder_by.direction
anenum
might come in handy. – Carsten