I'm having trouble with sealed classes. I get a specification from Micronaut-openapi, but the code generator I am using (orval) experiences a cyclic reference and fails.
Given this data class:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type",
visible = true
)
@JsonSubTypes(
JsonSubTypes.Type(name = "lounge", value = AnonymousResponse.Lounge::class),
JsonSubTypes.Type(name = "diningRoom", value = AnonymousResponse.DiningRoom::class)
)
sealed class AnonymousResponse {
abstract val id: Int
@JsonTypeName("lounge")
data class Lounge(
override val id: Int,
val hasTv: Boolean,
) : AnonymousResponse()
@JsonTypeName("diningRoom")
data class DiningRoom(
override val id: Int,
val hasTable: Boolean,
) : AnonymousResponse()
}
Micronaut-openapi generates the following components:
components:
schemas:
AnonymousResponse:
type: object
properties:
id:
type: integer
format: int32
discriminator:
propertyName: type
mapping:
lounge: '#/components/schemas/AnonymousResponse.Lounge'
diningRoom: '#/components/schemas/AnonymousResponse.DiningRoom'
oneOf:
- $ref: '#/components/schemas/AnonymousResponse.Lounge'
- $ref: '#/components/schemas/AnonymousResponse.DiningRoom'
AnonymousResponse.DiningRoom:
allOf:
- $ref: '#/components/schemas/AnonymousResponse'
- required:
- hasTable
- id
type: object
properties:
id:
type: integer
format: int32
hasTable:
type: boolean
AnonymousResponse.Lounge:
allOf:
- $ref: '#/components/schemas/AnonymousResponse'
- required:
- hasTv
- id
type: object
properties:
id:
type: integer
format: int32
hasTv:
type: boolean
Which leads to the following error in orval:
src/models/anonymousResponseDiningRoom.ts:10:13 - error TS2456: Type alias 'AnonymousResponseDiningRoom' circularly references itself.
10 export type AnonymousResponseDiningRoom = AnonymousResponse & AnonymousResponseDiningRoomAllOf;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/models/anonymousResponse.ts:11:13 - error TS2456: Type alias 'AnonymousResponse' circularly references itself.
11 export type AnonymousResponse = AnonymousResponseLounge | AnonymousResponseDiningRoom | AnonymousResponseOneOf;
~~~~~~~~~~~~~~~~~
src/models/anonymousResponseLounge.ts:10:13 - error TS2456: Type alias 'AnonymousResponseLounge' circularly references itself.
10 export type AnonymousResponseLounge = AnonymousResponse & AnonymousResponseLoungeAllOf;
~~~~~~~~~~~~~~~~~~~~~~~
I am not entirely sure whether it's the specification generator or the code generator doing something wrong, but the "allOf" - AnonymousResponse
references looks iffy to me, as (at least from how I read it) it would lead to e.g. Lounge
also containing information from DiningRoom
?
After trying placing a @Schema annotation on the sealed class, and looking into how to customise the automatic Schema generation, I realised this worked:
which ultimately resulted in the following orval code:
anonymousResponse.ts
anonymousResponseLounge.ts
anonymousResponseDiningRoom.ts
anonymousResponseOneOf.ts
And while it doesn't have constant values for the discriminator types, I don't think this is the fault of the spec.