swagger-ui
swagger-ui copied to clipboard
Ft/3803 multiple responses using one of attribute do not appear in ui
Description
Display oneOf/anyOf schema in Example View.
- Appears only on OAS3 specifications (obviously) and if an oneOf/anyOf structure is present on RequestBody or on Response
- By default the first oneOf/anyOf item is shown to keep the UI noise at a minimum
- Option to manually select oneOf/anyOf item
- config option to switch feature on/off (
showAlternativeSchemaExample: false)- could be removed in case the feature becomes standard
const ui = SwaggerUIBundle({
....
showAlternativeSchemaExample: true,
...
- Supports and covered with test cases
-
oneOf:
- of objects: example default: selects first item
- of primitive data types: example default: selects first item
- of arrays with oneOf subschemas: example default: selects first item
- of arrays of an object with an oneOf subschema: example default: object with first item of subschema
- uses discriminator's mapping values as example Swagger Inheritance and Polymorphism
-
anyOf:
- of objects: example default: selects first item
- of primitive data types: example default: selects first item
- of arrays with anyOf subschemas: all items are shown as example value
- of arrays of an object with an anyOf subschema: example default: object with first item of subschema
-
Not yet supported/considered:
- oneOf/anyOf of arrays of an object with an oneOf/anyOf subschema: all permutation of an oneOf/anyOf could be listed
- random selection or round-robin selection (is a bit non-deterministic and UI is leaner without)
Motivation and Context
Fixes #3803 Multiple responses using oneOf attribute do not appear in UI
How Has This Been Tested?
Swagger to demonstrate the feature
openapi: 3.0.1
info:
title: OneOf examples
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
version: 1.0.0
servers:
- url: localhost
paths:
/delivery-addresses/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
patch:
summary: Update delivery address
operationId: patchDeleiverAddress
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/DeliveryAddress'
application/xml:
schema:
$ref: '#/components/schemas/DeliveryAddress'
responses:
'200':
description: successful operation
x-content:
application/hal-form+json:
schema:
type: object
x-schemaRef: '#/components/schemas/DeliveryAddress'
get:
summary: Read delivery address
operationId: getDeliveryAddress
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/DeliveryAddress'
components:
schemas:
DeliveryAddress:
type: object
title: Delivery Address
description: OneOf Example
properties:
address:
type: string
city:
type: string
options:
oneOf:
- type: object
title: Delivery Express
required:
- company
properties:
company:
type: string
shipping:
type: string
default: STANDARD
example: STANDARD
enum:
- FAST
- STANDARD
- type: object
title: Parcel Quick
required:
- company
properties:
company:
type: string
remarks:
type: string
options2:
anyOf:
- type: object
title: US
properties:
state:
type: string
zipCode:
type: string
required:
- zipCode
- state
- type: object
title: Europe
properties:
county:
type: string
postCode:
type: string
required:
- postCode
Screenshots:
Checklist
My PR contains...
- [ ] No code changes (
src/is unmodified: changes to documentation, CI, metadata, etc.) - [ ] Dependency changes (any modification to dependencies in
package.json) - [ ] Bug fixes (non-breaking change which fixes an issue)
- [ ] Improvements (misc. changes to existing features)
- [x] Features (non-breaking change which adds functionality)
My changes...
- [ ] are breaking changes to a public API (config options, System API, major UI change, etc).
- [ ] are breaking changes to a private API (Redux, component props, utility functions, etc.).
- [ ] are breaking changes to a developer API (npm script behavior changes, new dev system dependencies, etc).
- [x] are not breaking changes.
Documentation
- [ ] My changes do not require a change to the project documentation.
- [ ] My changes require a change to the project documentation.
- [x] If yes to above: I have updated the documentation accordingly.
Automated tests
- [ ] My changes can not or do not need to be tested.
- [x] My changes can and should be tested by unit and/or integration tests.
- [x] If yes to above: I have added tests to cover my changes.
- [ ] If yes to above: I have taken care to cover edge cases in my tests.
- [x] All new and existing tests passed.
Merge it please!
Is this intended to only work with oneOf or anyOf as a child of a property definition like in the example above?
type: "object"
properties:
"options":
oneOf:
- …
- …
oneOf/anyOf can appear at the top level of a schema, too.
type: "object"
oneOf:
- …
- …
oneOf/anyOf at the top level

openapi: 3.0.1
info:
title: OneOf examples
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
version: 1.0.0
servers:
- url: localhost
paths:
/delivery-addresses/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
patch:
summary: Update delivery address
operationId: patchDeleiverAddress
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/DeliveryAddress'
application/xml:
schema:
$ref: '#/components/schemas/DeliveryAddress'
responses:
'200':
description: successful operation
x-content:
application/hal-form+json:
schema:
type: object
x-schemaRef: '#/components/schemas/DeliveryAddress'
get:
summary: Read delivery address
operationId: getDeliveryAddress
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/DeliveryAddress'
components:
schemas:
DeliveryAddress:
oneOf:
- type: object
title: Online Delivery
properties:
email:
type: string
example: [email protected]
- type: object
title: Delivery Address
description: OneOf Example
properties:
address:
type: string
city:
type: string
options:
oneOf:
- type: object
title: Delivery Express
required:
- company
properties:
company:
type: string
shipping:
type: string
default: STANDARD
example: STANDARD
x-oneOf:
- const: FAST
title: 24h + EUR 40
- const: STANDARD
title: 3-5 Days
- type: object
title: Parcel Quick
required:
- company
properties:
company:
type: string
x-const: PQ
remarks:
type: string
options2:
oneOf:
- type: object
title: US
properties:
state:
type: string
zipCode:
type: string
required:
- zipCode
- state
- type: object
title: Europe
properties:
county:
type: string
postCode:
type: string
required:
- postCode
Interesting. I tried your branch on my spec and couldn't get it to work. Is it because the children of my oneOf are $ref or because the parent schema has properties as well?
Interesting. I tried your branch on my spec and couldn't get it to work. Is it because the children of my
oneOfare$refor because the parent schema has properties as well?
Upps, interesting! I'll try to consider your scenario as well...
Interesting. I tried your branch on my spec and couldn't get it to work. Is it because the children of my
oneOfare$refor because the parent schema has properties as well?
Hi Hannes,
your use case works now too:

Cool! What do you think about adding support for discriminator? With my spec this would eliminate the issue that the example value for integration_type does not change depending on the selected alternative.
Also noticed that for lists of documents whose schema has a oneOf, the examples only represent a partial set of properties.
The "manually selected" UI element also doesn't populate a list of alternatives but I'm not sure that is needed here. It may make more sense to simply select the first alternative for the first document, the second alternative for the second document and so on.
The above screen shot is from the 200 response for the GET /portal/{portal_id}/integration path in my spec.
Cool! What do you think about adding support for discriminator? With my spec this would eliminate the issue that the example value for
integration_typedoes not change depending on the selected alternative.Also noticed that for lists of documents whose schema has a oneOf, the examples only represent a partial set of properties.
![]()
The "manually selected" UI element also doesn't populate a list of alternatives but I'm not sure that is needed here. It may make more sense to simply select the first alternative for the first document, the second alternative for the second document and so on.
-
Support for discriminator's mapping type added. But I've considered discriminator only at the same level as oneOf/anyOf like in the example of https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/ . I'm not sure if your spec is correct.
-
OneOf within array/items schema is now supported too
I can confirm that arrays work better now in that all item properties are populated. But the arrays have one item only. I would still consider generating multiple items and to round-rob through the oneOf alternatives. For a single item there is no choice than to pick one of the alternatives but for an array there is the opportunity to pick more than one. BTW: I would also consider using a random choice of alternative instead of the first. But maybe the non-determinism is undesirable.
The discriminator isn't working for me, even though in the latest version of my spec discriminator and oneOf are sibling properties (at the same level). An earlier version was more complicated and, as you suggest, probably incorrect. But the latest version closely resembles the example from the documentation that you refer to.
In the screen shot below (200 response from GET /portal/{portal_id}/integration/{integration_id}) the fourth oneOf alternative is selected but the discriminator property integration_type has the value mapped to the first alternative get. It should be get_manifest.
I would still consider generating multiple items and to round-rob through the
oneOfalternatives.
I agree, it could be a solution.
BTW: I would also consider using a random choice of alternative instead of the first. But maybe the non-determinism is undesirable.
I had a random choice in my initial proposal I've presented to my colleagues, but UI get's a bit non-deterministic and UI is leaner without.
The discriminator isn't working for me, even though in the latest version of my spec
discriminatorandoneOfare sibling properties (at the same level). An earlier version was more complicated and, as you suggest, probably incorrect. But the latest version closely resembles the example from the documentation that you refer to.In the screen shot below (200 response from
GET /portal/{portal_id}/integration/{integration_id}) the fourth oneOf alternative is selected but the discriminator propertyintegration_typehas the value mapped to the first alternativeget. It should beget_manifest.
With Pull request your example works. I'm not sure if this the only option we should support.
I see. The PR pushes the property down from the super-schema into each sub-schema. It would be suboptimal if that were the only solution because the point of oneOf and schema polymorphism is to not have to repeat common properties in sub-schemas.
Hi Hannes, with the latest update, discriminators of the super-schema are supported too :)
I tried it out and it works great! Thank you!
Hi @shockey,
The pull request has basically two parts:
- The sampleFromSchema function (scr/core/plugins/sample/fn) - which I've improved to handle various oneOf/anfOf use cases
- The visualisation part - which should/could be wrapped to enable other implementation
Is there anything I can do to help you pushing this pull request into master? What is missing?
Many thanks Erwin
oneOf/anyOf at the top level
openapi: 3.0.1 info: title: OneOf examples license: name: Apache 2.0 url: 'http://www.apache.org/licenses/LICENSE-2.0.html' version: 1.0.0 servers: - url: localhost paths: /delivery-addresses/{id}: parameters: - name: id in: path required: true schema: type: string patch: summary: Update delivery address operationId: patchDeleiverAddress requestBody: content: application/json: schema: $ref: '#/components/schemas/DeliveryAddress' application/xml: schema: $ref: '#/components/schemas/DeliveryAddress' responses: '200': description: successful operation x-content: application/hal-form+json: schema: type: object x-schemaRef: '#/components/schemas/DeliveryAddress' get: summary: Read delivery address operationId: getDeliveryAddress responses: '200': description: successful operation content: application/json: schema: $ref: '#/components/schemas/DeliveryAddress' components: schemas: DeliveryAddress: oneOf: - type: object title: Online Delivery properties: email: type: string example: [email protected] - type: object title: Delivery Address description: OneOf Example properties: address: type: string city: type: string options: oneOf: - type: object title: Delivery Express required: - company properties: company: type: string shipping: type: string default: STANDARD example: STANDARD x-oneOf: - const: FAST title: 24h + EUR 40 - const: STANDARD title: 3-5 Days - type: object title: Parcel Quick required: - company properties: company: type: string x-const: PQ remarks: type: string options2: oneOf: - type: object title: US properties: state: type: string zipCode: type: string required: - zipCode - state - type: object title: Europe properties: county: type: string postCode: type: string required: - postCode
Hi !,
Great job you've done here! So sorry I'm kinda new to swagger and I need to see if the multiple payload in a single endpoint would be possible,
I've tried building the latest changes you've done, but it's currently not working on my end. The steps I did was npm install npm run build then copy the dist files to my apache server then updated the index.html to point to the same yaml file listed in this quoted link.
the page i'm getting.

Any help from you would be great !
Thanks, Cedric
Hi !,
Great job you've done here! So sorry I'm kinda new to swagger and I need to see if the multiple payload in a single endpoint would be possible,
I've tried building the latest changes you've done, but it's currently not working on my end. The steps I did was npm install npm run build then copy the dist files to my apache server then updated the index.html to point to the same yaml file listed in this quoted link.
the page i'm getting.
Any help from you would be great !
Thanks, Cedric
Adam prepared an published a release > https://github.com/swagger-api/swagger-ui/issues/3803#issuecomment-561344844 btw thanks Adam!
or you might just didn't realized to add the option to switch feature on/off (showAlternativeSchemaExample: false)
- could be removed in case the feature becomes standard
const ui = SwaggerUIBundle({
....
showAlternativeSchemaExample: true,
...
Ah !
I manually grepped the showAlternativeSchemaExample on the dist folder and the apache serve I'm hosting and found the issue. It seems that I was not overwritting properly on the apache server itself !
Thank you so much !
@tim-lai @hkosova @Simran-B @shockey @webron could you merge it please?
wonder why this is not merged? :- )
@tim-lai @hkosova @Simran-B @shockey @webron what do you still need to be able to merge this PR? Let us know, so that we can help you address those things and get this awesome work, anticipated by hundreds of devs, merged.
@VIIgit special thanks for making this possible!, kudos!
btw, Redoc, your competitor, advertises support for polymorphism as one of their killer features... Just saying.
I'd expect the maintainers to at least clarify what they intent to do with this PR. If current workload prevents them from even looking at it, that's fine. I have a day job, too. But it takes 30s to type that into a comment. Radio silence is not in the spirit of open source, especially considering that contributions are explicitly encouraged.
I am still getting (no example available) even after trying to follow the examples above. The schema shows the structure but there are no examples shown or options to select options

I am still getting (no example available) even after trying to follow the examples above. The schema shows the structure but there are no examples shown or options to select options
just to make sure: you might need add the option showAlternativeSchemaExample to switch feature on (could be removed in case the feature becomes standard):
const ui = SwaggerUIBundle({
....
showAlternativeSchemaExample: true,
...
I was actually testing it on the editor. But I have also tested it locally with the option and still shows (no example available). Am I missing something in my implementation?
I was actually testing it on the editor. But I have also tested it locally with the option and still shows (no example available). Am I missing something in my implementation?
see #3803 for a released and packaged Swagger UI. For the editor would you need to do it by yourself or wait til it's getting merged ....
@VIIgit any plans to support xml?? I have no xml rendered:


"CertTypeEnum":
title: "CertTypeEnum"
type: string
enum:
- "CA"
- "CERT"
"CertificateAuthorityBean":
title: "CertificateAuthorityBean"
type: object
required:
- "certExpiration"
- "certName"
- "certType"
properties:
"certExpiration":
description: "Certificate expiry date"
type: string
"certName":
pattern: '^(?=.*\S).+$'
description: "Certificate name"
type: string
"certType":
$ref: "#/components/schemas/CertTypeEnum"
"CertificateOrdinaryBean":
title: "CertificateOrdinaryBean"
type: object
required:
- "certExpiration"
- "certName"
- "certType"
- "parentId"
properties:
"certExpiration":
description: "Certificate expiry date"
type: string
"certName":
pattern: '^(?=.*\S).+$'
description: "Certificate name"
type: string
"certType":
$ref: "#/components/schemas/CertTypeEnum"
"parentId":
type: integer
format: int64
"CertificateCommand":
oneOf:
- $ref: "#/components/schemas/CertificateAuthorityBean"
- $ref: "#/components/schemas/CertificateOrdinaryBean"
discriminator:
propertyName: "certType"
mapping:
"CA": "#/components/schemas/CertificateAuthorityBean"
"CERT": "#/components/schemas/CertificateOrdinaryBean"
To be honest I'm a bit disappointed as I like the SwaggerUI/SwaggerEditor very much and I miss a better support for oneOf/anyOf too. Regardless if it's this proposed solution or any other solution.
But this Pull Request is waiting for more than a half year to be merged. Until now, I haven't received any official feedback nor improvements which needs to be done before the request can be accepted. So I'm sadly not investing any more time on this repository. I may look even for alternatives
@webron ping. Please.