Reputation: 6204
I have following JSONs:
[
{
"type": "message",
"payload": {
"message": "some message"
}
},
{
"type": "image",
"payload": {
"url": "http://example.com/foo/bar"
}
},
{
"type": "video",
"payload": {
"url": "http://example.com/foo/baz"
}
}
]
And I would like to validate:
type == message
then payload
should have message
type in image, video
then payload
should have url
I figure something like:
{
"type": "object",
"properties": {
"type": {
"enum": ["message", "image", "video"]
},
"payload": {
"type": "object",
"oneOf": [
{
"properties": {
"message": {
"type": "string"
}
},
"required": ["message"]
},
{
"properties": {
"url": {
"type": "string"
}
},
"required": ["url"]
}
]
}
}
}
But this not valid well when e.g.: type
is message
and payload
has url
.
Upvotes: 1
Views: 282
Reputation: 24439
Using oneOf
for this type of thing is terrible for error messaging. Here's an alternative using if
/then
that's more verbose, but is better for error messaging and performance.
{
"type": "object",
"properties": {
"type": { "enum": ["message", "image", "video"] },
"payload": {
"message": { "type": "string" },
"url": { "type": "string", "format": "uri" }
}
},
"allOf": [
{
"if": {
"properties": {
"type": { "const": "message" }
},
"required": ["type"]
},
"then": {
"properties": {
"payload": { "required": ["message"] }
}
}
},
{
"if": {
"properties": {
"type": { "enum": ["image", "video"] }
},
"required": ["type"]
},
"then": {
"properties": {
"payload": { "required": ["url"] }
}
}
}
]
}
Upvotes: 2
Reputation: 725
you should move the oneOf
up to describe the whole message/image/video object, and replace the enum
for the "type" property with individual const
values across the oneOf
schemas:
{
"type": "object",
"oneOf": [
{
"properties": {
"type": {
"const": "message",
},
"payload": {
(message payload schema)
}
}
},
{
"properties": {
"type": {
"const": "image",
},
"payload": {
(image payload schema)
}
},
}
]
}
Upvotes: 3