I'd like one schema to validate two different types of objects that have a lot of overlap. Consider the following json Schema:
{
"properties": {
"a":{"const":1}
},
"oneOf": [
{ "properties": { "b":{"const":2}}},
{ "properties": { "c":{"const":3}}}
],
"additionalProperties":false
}
obviously, this will always fail, because the object must have "a" and only "a" and also have either "b" or "c", which is a contradiction.
I could of course rearrange it like so:
{
"oneOf": [
{ "properties": { "a":{"const":1}, "b":{"const":2}}, "additionalProperties": false},
{ "properties": { "a":{"const":1}, "c":{"const":3}}, "additionalProperties": false}
]
}
And this is my intended behavior. But I don't love it. because there's no reusing the rules on "a". What if there are many many properties I need to reuse? I like something of the form like the first schema presented, but that functions like the second schema. Is it possible to reuse the rules for "a" and get the intended function?
You can take your first approach and use unevaluatedProperties
instead of additionalProperties
. (docs)
additionalProperties
can't "see into" subschemas of adjacent keywords, but unevaluatedProperties
can and was added specifically for this purpose.
{
"properties": {
"a":{"const":1}
},
"oneOf": [
{ "properties": { "b":{"const":2}}},
{ "properties": { "c":{"const":3}}}
],
"unevaluatedProperties":false
}
You need to be using at least draft 2019-09 to have the unevaluatedProperties
keyword. Ideally, you want to specify $schema
(and $id
) anyway.
You can test this on my playground, https://json-everything.net/json-schema.