-
-
Notifications
You must be signed in to change notification settings - Fork 308
Description
Context
The overlap in specification between AsyncAPI and OpenAPI specs allows the combining of common models across both.
Example:
./models/foo.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
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
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:
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.:
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.