Details of model composition should be documented
See original GitHub issueOASv3.0 says:
The OpenAPI Specification allows combining and extending model definitions using the allOf property of JSON Schema, in effect offering model composition. allOf takes an array of object definitions that are validated independently but together compose a single object.
However, the spec does not define how this composition should be done. In particular, it is unclear how to interpret an “allOf” composition when a property appears in more than one component of the “allOf”. For example, in this schema:
"Thing": {
"allOf": [
{
"properties": {
"foo": {
"type": "string"
}
}
},
{
"properties": {
"foo": {
"type": "string"
}
},
"required": [
"foo"
]
}
]
},
it is not clear from the specification whether foo
is required or optional in the Thing
schema.
Multiple interpretations are possible, including “first occurrence of the property wins” or “last occurrence of the property wins”. However, to be consistent with JSON Schema, it seems that we need a more complicated interpretation. The JSON Schema spec says:
An instance validates successfully against [allOf] if it validates successfully against all schemas defined by this keyword’s value.
To be consistent with JSON schema, it seems that we should “compose” like-named properties in a “allOf” in a way that produces the “most restrictive” property definition. For example, a property that is required in any component of the “allOf” would be required in the composed model. Or if one property specifies a maximum, the composed property would have that maximum.
Whether it is the “composed property” interpretation or some other that is appropriate, it should be clearly documented in the spec.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:15 (9 by maintainers)
Top GitHub Comments
@spacether it’s too late at night here for me to attempt schema algebra but let me sketch out a few things:
oneOf
a lot here, andoneOf
is much more complex to work with thanallOf
. You usually can’t rearrange a schema to totally eliminate aoneOf
, except in a few cases where other keywords produce similar behavior (e.g. the array form oftype
or certain arrangements ofif
/then
/else
).not
is the really hard one, actually- you can reworkoneOf
into a combination ofallOf
s andnot
s but that’s really hard to read.allOf
, you can generally collapse it, although it’s non-trivial and some cases cannot be collapsed because they involve the same keyword used multiple times in a way that is not contradictory and cannot be reduced to one use of the keyword. I wrote a partial implementation of this back in the draft-07 days, although I don’t think that package has been significantly maintained since I left that job.As you can see if you poke around in that repo, I did the collapsing because we were using schemas for documentation and having a ton of
allOf
s show up when they were often just artifacts of making schemas modular rather than being significant to end-users cluttered the documentation. So I was reducing that clutter as much as possible. It’s debatable as to whether that’s really the “right” thing to do. But that sort of thing- reducing clutter without changing functionality- is the main reason I’d ever do that. As far as validation, there’s no reason to collapse things.If you’re making use of annotations, which your application might interpret based on their location in the schema (e.g. a
title
outside of a$ref
might override one inside of the$ref
) then doing a lot of de-referencing and collapsing is not advised.Philosophically, I’d like to encourage folks to design annotation vocabularies (now that extension vocabularies are supported in OAS 3.1 and JSON Schema 2020-12) to give tools hints as to how to handle things like
allOf
. You can find examples of this in other issues here. But the general idea is to add keywords that don’t do any validation, but indicate whether an adjacent**allOf
should be treated as composition or some sort of inheritance for code generation purposes. The validation is the same either way. This is how I want to bridge the gap between JSON Schema being a constraint validation system while tools like code and documentation generation want a data definition language. These are not the same things, and a lot of difficult problems have arisen by trying to make a constraint system a data definition system. Annotations provide a flexible way to solve those problems.**adjacent keywords are keywords in the same schema object
As one of the editors of the JSON Schema spec, I would prefer this 😃
More broadly, I am hoping that we can converge the JSON Schema spec and Open API uses of JSON Schema spec to the point where little or even no special wording on the part of OAI is necessary, primarily through improving the modularity of JSON Schema. Embedding a subset of JSON Schema into a larger document is done in several projects (OAI is the largest that I know of) so we should address that on the JSON Schema spec side.