Description
So I realize there is some discussions regarding some "similar" things, but I'm not quite sure they're similar enough - if so, please say so and I'll contribute to the other discussions accordingly and close this one out. Other similar but not quite as extensive discussions I have found:
- Extra JSON Reference properties ignored - reduces reusability of referencesย #556 : polymorphism around $ref
- Support for multiple $refs inside a single objectย #417 : paths and $ref
Basically, one should be able to write their OpenAPI specification in as DRY a manner as possible. Presently this is not possible because:
$ref
is not valid at all the right placesallOf
is not valid at the right places (which could make up for point 1)$ref
can't be specified numerous times next to itself appropriately
Let's give this some better clarity via an example. Discussing API Header Fields provides a good example such as the following which similar to #417 but I'm going more general where that seems to be focused on path objects:
paths:
/:
get:
parameters:
- $ref: `#/components/headers/x-my-header-1`
- $ref: `#/components/headers/x-my-header-3`
responses:
'401':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
'403':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
'200':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-2`
$ref: `#/components/headers/x-my-header-3`
'301':
headers:
allOf:
- $ref: `#/components/headers/x-my-header-1`
- $ref: `#/components/headers/x-my-header-2`
- $ref: `#/components/headers/x-my-header-3`
default:
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
post:
parameters:
- $ref: `#/components/headers/x-my-header-1`
- $ref: `#/components/headers/x-my-header-2`
responses:
'401':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
'403':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
'200':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-2`
$ref: `#/components/headers/x-my-header-3`
default:
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
/howdy:
delete:
parameters:
- $ref: `#/components/headers/x-my-header-1`
- $ref: `#/components/headers/x-my-header-2`
responses:
'401':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
'403':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
'200':
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-2`
$ref: `#/components/headers/x-my-header-3`
default:
headers:
$ref: `#/components/headers/x-my-header-1`
$ref: `#/components/headers/x-my-header-3`
components:
headers:
x-my-header-1:
required: true
description: my first header
schema:
type: string
format: uuid
x-my-header-2:
required: true
description: my second header
schema:
type: string
x-my-header-3:
required: true
description: my third header
schema:
type: integer
The above is missing a lot of stuff, but only in order to show the re-use and avoid having to put a complete spec here. I know some of the above can be fixed by moving up a layer in the referencing, e.g create a component for the header set and reference that instead; however that can then dictate a bad spec by forcing all headers to be pushed to header sets which then can also be an issue for 1-off header combinations.
Goal here is to enable spec writers to manage their specifications by creating re-usable modules that can be continuously re-used. To achieve this, $ref
would need to be valid in essentially ever object to replace anything in the object. F.e if you have a description
field you want to re-use, define it once and use it 10 times.
Two parallel $ref
values should be valid and able to point to separate objects, neither being discarded, or allOf
could be used to combine the contents of both $ref
references to create the same effect (good solution for one-offs).
When building larger APIs using tooling like OpenAPI being able to be a DRY as possible is key to keeping bugs from creeping into the specs as it reduces the ability for any one instance to be mis-typed. For instance, if you had to type x-my-header-3
for every single Request object and x-my-header-2
for every single Response object - one typo of my-header-3
or xmy-header-3
could easily create something hard to detect where using the $ref objects would make it fail validation and be easily caught in gate checks (PR builders, etc).
To re-iterate - please let me know if I need to file this with JSON Reference/Schema too. I did not find anything suitably talking about these aspects while reading through any of the repos I came across, but have in general there does seem to be some of sentiment that this is an issue.