-
-
Notifications
You must be signed in to change notification settings - Fork 306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue: subset schemas don't work with unevaluatedProperties
across oneOf
branches
#1585
Comments
It sounds to me like you're trying to model a polymorphic system, which has historically been a problem for JSON Schema. Notably, JSON Schema is a constraint system, not a data modelling system. As such, it has a really hard time representing polymorphic types. What I've typically seen done is encode a "type" property in your data model. This can then be used along with a {
"type": "object",
"properties": {
"a": true,
"b": true,
"c": true
},
"required": ["type"],
"oneOf": [
{
"properties": {
"type": { "const": "a" }
},
"required": ["a"]
},
{
"properties": {
"type": { "const": "b" }
},
"required": ["b"],
"not": { "required": ["c"] }
},
{
"properties": {
"type": { "const": "ab" }
},
"required": ["a", "b"]
},
]
} Note This operates very similarly to OpenAPI's This would validate
and would fail
Notice that to restrict In regard to |
Thanks @gregsdennis , Yeah it would be nice if I could add a Chatting with @hudlow, with firstOf:
- required: ['a']
properties:
a: {}
- required: ['a', 'b']
properties:
a: {}
b: {}
- required: ['a', 'b', 'c']
properties:
a: {}
b: {}
c: {} with if/then chain unevaluatedProperties: false
if:
required: ['a']
properties:
a: {}
then:
if:
required: ['a', 'b']
properties:
a: {}
b: {}
then:
required: ['a', 'b', 'c']
properties:
a: {}
b: {}
c: {} |
I can't figure out how to set up mutual exclusion of subset schemas elegantly.
I thought
unevaluatedProperties
was the solution so that I can easily reject properties of the superset schema that don't appear in the subset schema, but I can't find the right pattern to set it up right.Subset and Superset schemas
Let's define subset schema as such:
Similarly,
Rationale
I have a real world schema with 2 kinds of values. But the first option happens to be a subset of the second
option. I'd like to make it so that if the subset schema validates, the superset schema will not validate.
Attempt 1 - Use
not
- PASSThis one works as expected, where
{"a": true, "b": true}
only validates against the second of the oneOf options, but I have to nest the meat of the second option inside a not of the first. This is ugly, but effective. When I compose my schemas, I don't want to reference all possible superset schemas in the subset schema.Attempt 2 - Use
anyOf
- PASSThis approach gives up on the "typing" quality of the oneOf where consumers of the instance can learn about the "type" of the schema by inspecting which branch validates. Consumers need more sophistication since both validate for
{"a": true, "b": true}
.Attempt 3 - Use
unevaluatedProperties
at the top level - FAILFor this instance,
{"a": true, "b": true}
, validation will fail on theoneOf
since both branches validate and the collected annotations from the valid oneOf branches make both"a"
and"b"
evaluated properties.Attempt 4 - push unevaluatedProperties to child schemas - FAIL
If I push down
unevaluatedProperties: false
, I get the same issue as we have withadditionalProperties: false
, schemas can not be extended if a parent "tacks on" some more properties.If I try this JSON, the second oneOf will fail on
unevaluatedProperty
:"c"
Attempt 5 - Introduce new in-place applicator
firstOf
: PASSLet's define a new in place applicator,
firstOf
Both branches validate this instance,
{"a": true, "b": true}
, but only annotations from the first branchare collected. This causes
unevaluatedProperties
to disregard annotations from the second branch and thereby reject property"b"
as "unevaluated".The text was updated successfully, but these errors were encountered: