According to swagger docs polymorphism can be supported using oneOf and discriminator. This way we can achieve polymorphic API responses and polymorphic properties on objects.
However, looks like smallrye open api does not have ability to generate such open api schema. Automatically when mp.openapi.extensions.smallrye.auto-inheritance=BOTH is enabled. It is only possible by manually adding polymorphism to @Schema on fields and @ApiResponse
Suppose we have the following simple class hierarchy. Note: type on BaseClass is used as discriminator.
@Schema
public class BaseClass {
private String baseField;
private String type;
private FieldBaseClass someObjectField;
}
@Schema
public class FieldBaseClass {
private String baseFieldClassField;
}
@Schema
public class FirstLevelFieldClass extends FieldBaseClass {
private String firstLevelFieldClassField;
}
@Schema
public class FirstLevelSubclass extends BaseClass{
private String firstLevelClassField;
}
@Schema
public class SecondLevelSubclass extends FirstLevelSubclass{
private String secondLevelClassField;
}
Also, there is a simple Jax-Rs endpoint
@Path("/hello")
public class ExampleResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public BaseClass hello() {
return new BaseClass();
}
}
The resulting OpenApi spec is as follows (with mp.openapi.extensions.smallrye.auto-inheritance=BOTH)
---
openapi: 3.0.3
info:
title: demo API
version: 1.0-SNAPSHOT
paths:
/hello:
get:
tags:
- Example Resource
responses:
"200":
description: OK
content:
text/plain:
schema:
$ref: "#/components/schemas/BaseClass"
components:
schemas:
BaseClass:
type: object
properties:
baseField:
type: string
type:
type: string
someObjectField:
$ref: "#/components/schemas/FieldBaseClass"
FieldBaseClass:
type: object
properties:
baseFieldClassField:
type: string
FirstLevelFieldClass:
allOf:
- $ref: "#/components/schemas/FieldBaseClass"
- type: object
properties:
firstLevelFieldClassField:
type: string
FirstLevelSubclass:
allOf:
- $ref: "#/components/schemas/BaseClass"
- type: object
properties:
firstLevelClassField:
type: string
SecondLevelSubclass:
allOf:
- $ref: "#/components/schemas/FirstLevelSubclass"
- type: object
properties:
secondLevelClassField:
type: string
Expected result:
- Response for /hello must contain polymorphic oneOf schema with discriminator and mapping
- someObjectField of class BaseClass has a polymorphic oneOf schema with discriminator and mapping
- User of library can specify discriminator property on base class
- User of library can specify discriminator mapping for each subclass. Then this mapping will be used to generate syncthetic polymorphic schema
For example, smallrye should add syncthetic polymorphic schema to schemas, which can look like this:
---
openapi: 3.0.3
info:
title: demo API
version: 1.0-SNAPSHOT
paths:
/hello:
get:
tags:
- Example Resource
responses:
"200":
description: OK
content:
text/plain:
schema:
$ref: "#/components/schemas/PolymorphicBaseClass"
components:
schemas:
PolymorphicBaseClass:
type: object
oneOf:
- $ref: "#/components/schemas/BaseClass"
- $ref: "#/components/schemas/FirstLevelSubclass"
- $ref: "#/components/schemas/SecondLevelSubclass"
discriminator:
propertyName: type
mapping:
baseType: "#/components/schemas/BaseClass"
firstType: "#/components/schemas/FirstLevelSubclass"
secondType: "#/components/schemas/SecondLevelSubclass"
PolymorphicFieldBaseClass:
type: object
oneOf:
- $ref: "#/components/schemas/FieldBaseClass"
- $ref: "#/components/schemas/FirstLevelFieldClass"
discriminator:
propertyName: type
mapping:
baseFieldType: "#/components/schemas/FieldBaseClass"
firstFieldType: "#/components/schemas/FirstLevelFieldClass"
BaseClass:
type: object
properties:
baseField:
type: string
type:
type: string
someObjectField:
$ref: "#/components/schemas/PolymorphicFieldBaseClass"
FieldBaseClass:
type: object
properties:
baseFieldClassField:
type: string
FirstLevelFieldClass:
allOf:
- $ref: "#/components/schemas/FieldBaseClass"
- type: object
properties:
firstLevelFieldClassField:
type: string
FirstLevelSubclass:
allOf:
- $ref: "#/components/schemas/BaseClass"
- type: object
properties:
firstLevelClassField:
type: string
SecondLevelSubclass:
allOf:
- $ref: "#/components/schemas/FirstLevelSubclass"
- type: object
properties:
secondLevelClassField:
type: string
Such ploymorphic API spec is extremely important for some forontend TS consumers. For example, popylar rtk-query lib for frontend can not generate polymorphic API without explicit polymorphic typs declaration (using oneOf and discriminator). In addition, polymorphic API gives human consumers ability to define class hierarchy and used discriminator types just by looking at spec.
According to swagger docs polymorphism can be supported using
oneOfanddiscriminator. This way we can achieve polymorphic API responses and polymorphic properties on objects.However, looks like smallrye open api does not have ability to generate such open api schema. Automatically when
mp.openapi.extensions.smallrye.auto-inheritance=BOTHis enabled. It is only possible by manually adding polymorphism to@Schemaon fields and@ApiResponseSuppose we have the following simple class hierarchy. Note: type on BaseClass is used as discriminator.
Also, there is a simple Jax-Rs endpoint
The resulting OpenApi spec is as follows (with
mp.openapi.extensions.smallrye.auto-inheritance=BOTH)Expected result:
For example, smallrye should add syncthetic polymorphic schema to schemas, which can look like this:
Such ploymorphic API spec is extremely important for some forontend TS consumers. For example, popylar rtk-query lib for frontend can not generate polymorphic API without explicit polymorphic typs declaration (using oneOf and discriminator). In addition, polymorphic API gives human consumers ability to define class hierarchy and used discriminator types just by looking at spec.