Discriminator support to be aligned with OAS3
- Dominant language
- JavaScript
- Stars
- 5.3k
- Forks
- 382
- Avg merge
- 7m
- Merged PRs (30d)
- 4
Description
# Context
The overlap in specification between AsyncAPI and OpenAPI specs allows the combining of common models across both.
Example:
./models/foo.yaml
```yaml
openapi: 3.1.0
info:
title: foo-models
description: Models for Foo
contact:
name: Foo Team
version: 1.0.0
paths: { }
components:
schemas:
Foo:
type: object
properties:
id:
type: string
```
./apis/foo.openapi.ayml
```yaml
openapi: "3.1.0"
info:
title: "foo"
description: "API Specifications for `foo`."
version: "1.0.0"
servers:
- url: http://localhost:8080/
description: Local Dev
paths:
/foo:
get:
summary: "Get Foos"
description: "Get Foos"
operationId: "getFoos"
responses:
"200":
description: "OK"
content:
'application/json':
schema:
type: array
items:
$ref: "../models/foo.yaml#/components/schemas/Foo"
```
./events/foo.asyncapi.ayml
```yaml
asyncapi: 3.0.0
info:
title: foo Events
version: 1.0.0
servers:
foo-local:
host: localhost:1234
protocol: foo
description: Foo broker (local dev)
security:
- $ref: '#/components/securitySchemes/plainSecurity'
defaultContentType: application/json
channels:
FooEvents:
address: foo.events
description: The topic on which foo events are published on.
messages:
fooQueriedEvent:
$ref: '#/components/messages/fooQueriedEvent'
operations:
'foo.queried':
action: send
channel:
$ref: '#/channels/FooEvents'
messages:
- $ref: '#/channels/FooEvents/messages/fooQueriedEvent'
components:
messages:
fooQueriedEvent:
name: fooQueriedEvent
title: Foo Queried Event
summary: Foo Queried Event
description: Foo Queried Event
contentType: application/json
payload:
$ref: '../models/foo.yaml#/components/schemas/Foo'
securitySchemes:
plainSecurity:
type: plain
description: Plain unauthenticated connection
```
# Problem
It's quite evident that AsyncAPI in general has no compatibility issues with OpenAPI specifications.
However, the problem lies with the use of `discriminator` in a `oneOf` situation.
If I update `./models/foo.yaml` to this:
```yaml
openapi: 3.1.0
info:
title: foo-models
description: Models for Foo
contact:
name: Foo Team
version: 1.0.0
paths: { }
components:
schemas:
Foo:
type: object
properties:
id:
type: string
bazAttributes:
$ref: '#/components/schemas/OneOfBazAttributes'
OneOfBazAttributes:
type: object
properties:
type:
type: string
enum: [ 'RealBaz', 'MockBaz' ]
discriminator:
propertyName: type
mapping:
RealBaz: '#/components/schemas/RealBazAttributes'
MockBaz: '#/components/schemas/MockBazAttributes'
RealBazAttributes:
allOf:
- $ref: '#/components/schemas/OneOfBazAttributes'
type: object
properties:
bazId:
type: string
MockBazAttributes:
allOf:
- $ref: '#/components/schemas/OneOfBazAttributes'
type: object
properties:
xyzId:
type: string
```
| Output | Result |
| ------- | ------ |
| OpenAPI | Works as expected |
| AsyncAPI | Fails with `"discriminator" property type must be string channels.FooEvents.messages.fooQueriedEvent.payload.properties.bazAttributes.discriminator` |
This is using the official `asyncapi` CLI binary provided by `asyncapi/cli:2.6.0` docker image, but also any other AsyncAPI tool I could find.
# Root Cause
From what I can understand, AsyncAPI implements `discriminator` using the schema that OpenAPI 2.x (Swagger) had, i.e.:
```yaml
OneOfBazAttributes:
type: object
properties:
type:
type: string
enum: [ 'RealBazAttributes', 'MockBazAttributes' ]
discriminator: type
# with the expectation of having the value of `type` matching
# the object name exactly as defined in the YAML
```
_(although the AsyncAPI render does not render any `oneOf` options, but all validations now pass successfully)._
OpenAPI moved to a newer schema in 3.x, and whilst AsyncAPI does not seem to have problems with the OpenAPI 3.x schema compatibility, the specific `discriminator` capability seems to still be stuck in the 2.x world.
As it is, I do not see any clean way to be able to support `discriminator` and both OpenAPI and AsyncAPI simultaneously, without fixing this issue, or rolling everything back to 2.x.
# Proposal
Align the AsyncAPI spec around `discriminator` to that of OpenAPI 3.1.x, and release it as AsyncAPI 3.1.0.
---
Keen to see your thoughts.
Thanks anyone participating.
Contributor guide
Research direction
Reproduce the reported validation with the asyncapi/cli:2.6.0 Docker image using the models/foo.yaml and events/foo.asyncapi.ayml examples. Review the specification guidance in CONTRIBUTING.md and the discriminator definition; done means the OpenAPI 3.1 mapping form validates in AsyncAPI while preserving the existing form.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- yaml
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100