Overriding object keys in allOf - valid or undefined behaviour?
See original GitHub issueHey all! I build fairly large APIs but always try to keep the schemas 1. reusable and 2. logically separated.
One requirement I often run into is the ability for the representation of a field to differ slightly to the mutable version. One example would be prices or monetary values in general.
When doing patch calls, I want to accept numbers but when getting the data, I want to return strings (or, in my case, a more complex object that contains a currency, a pre-formatted representation, the raw/inaccurate Float32/Number value, etc)
So what I’ve settled on is something like this:
openapi: 3.0.0
info:
title: "Example of allOf key precedence"
version: "0.0.0"
contact: {}
paths: {}
components:
schemas:
ProductImmutable:
type: object
properties:
price:
type: string
ProductMutable:
type: object
properties:
price:
type: number
Product:
type: object
allOf:
- { $ref: "#/components/schemas/ProductMutable" }
- { $ref: "#/components/schemas/ProductImmutable" }
Now this works, my code generates as expected. My PATCH endpoint can use just the mutable schema and the GET endpoint can use the full “Product” schema and show everything at once. All the validators and UIs render this correctly and as desired, the most recent entry into the allOf
list overrides earlier conflicting keys.
But what I want to know is, is this a valid and acceptable way to do this? It’s really concise and I’d hate to have to define these schemas twice (one for the patch and one for the get).
I don’t want to be relying on undefined behaviour. I can’t find any definitive answer in the reference. Both my frontend and backend code generation tools are generating valid code though.
Thanks!
Issue Analytics
- State:
- Created a year ago
- Comments:7 (1 by maintainers)
Top GitHub Comments
@Southclaws anything that does any sort of overriding or merging of schema assertions (any keyword that can cause validation to fail) or applicators (any keyword that applies a schema to an instance location, including
$ref
and all the keywords with subschemas in their values) is not compliant with the JSON Schema specifications.Some code generation tools in particular seem to impose semantics on the ordering of keywords like
allOf
but that behavior is implementation-specific.Annotation keywords (like
title
) defer handling of multiple values to the application (from JSON Schema’s point of view, both the OpenAPI specification and all implementations of it are “applications”). But those are the only keywords that do that. And some annotations (likereadOnly
andwriteOnly
) have pretty clear semantics that applications shouldn’t change (e.g. if any schema marks a field asreadOnly
it should be considered read-only).Generally what you want to do is factor out the properties that vary and only pull them in at the point where they are needed.
Handling variations that depend on HTTP context (e.g. PATCH vs GET) is a very complex topic without a clear solution. It’s something we’re discussing a lot for 4.0 (although I think an extension could be done for 3.1 as well).
Or a bit simpler: