То, что вы просите, является довольно распространенным требованием. Использование oneOf
/ anyOf
должно доставить вас туда, куда вы хотите.
В тех случаях, когда альтернативы являются взаимоисключающими (из-за разных значений id), я предпочитаю anyOf
чтобы позволить валидатору схемы прекратить проверку при обнаружении первой совпадающей подсхемы - тогда как oneOf
подразумевает, что все другие альтернативы не должны совпадать, например, в случае "id": 1
валидатору нужно будет только проверять первую подсхему в anyOf
чтобы указать, что он действителен, в то время как для oneOf
ему нужно будет проверить другие 29, чтобы убедиться, что они также недействительны. Но вы можете найти oneOf
более выразительным для людей-потребителей вашей схемы.
Для вашего конкретного сценария я бы представил что-то вроде следующей схемы:
{
"type": "object",
"required": ["message"],
"properties": {
"message": {
"type": "object",
"required": ["id", "correlationId", "payload"],
"properties": {
"id": { "enum": [1, 2, 3] },
"correlationId": { "type": "string" },
"payload": { "type": "object" }
},
"anyOf": [
{
"properties": {
"id": { "const": 1 },
"payload": { "$ref": "#/definitions/payload1" }
}
},
{
"properties": {
"id": { "const": 2 },
"payload": { "$ref": "#/definitions/payload2" }
}
},
{
"properties": {
"id": { "const": 3 },
"payload": { "$ref": "#/definitions/payload3" }
}
},
]
}
},
"definitions": {
"payload1": {
"type": "object",
"required": ["amount"],
"properties": {
"amount": { "type": "integer" }
}
},
"payload2": {
"type": "object",
"required": ["code"],
"properties": {
"code": { "type": "string" }
}
},
"payload3": {
"type": "object",
"required": ["foo"],
"properties": {
"foo": { "type": "string" }
}
}
}
}