Can I have a polymorphic property that is not of type "Object"?
Hello.
I am trying to come up with a single openapi.yaml that would serve for both code generation and API documentation.
However, I'm having troubles with reaching both goals with a single file because of a polymorphism.
Every time I try I either get ugly "Example Values" in the online documentation or just blunt "Object" types in generated classes or both.
Let me illustrate: I have two endpoints, one of which returns a single polymorphic object and other returns a list of these.
That is "GET /allPets" - would yield a list of Pets and Dogs and "GET /randomPet" would return a single Pet.
If I would be writing my classes in a plain Java, then Pet would be an abstract class or an interface and Cat and Dog would inherit from/implement it. Therefore this abstract type would be used for both endpoints.
However, this is not something I achieve with OpenAPI. May be I am just approaching the problem from the wrong end.
Here is the definition:
openapi: "3.0.0"
info:
version: 1.0.0
title: PetStore
paths:
/randomPet:
get:
responses:
'200':
description: "a single random pet"
content:
application/json:
schema:
$ref: '#/components/schemas/SinglePetResponse'
/allPets:
get:
responses:
'200':
description: "a single random pet"
content:
application/json:
schema:
$ref: '#/components/schemas/AllPetsResponse'
components:
schemas:
SinglePetResponse:
type: object
properties:
pet:
oneOf:
- $ref: "#/components/schemas/Dog"
- $ref: "#/components/schemas/Cat"
discriminator:
propertyName: pet_type
AllPetsResponse:
type: array
items:
oneOf:
- $ref: "#/components/schemas/Dog"
- $ref: "#/components/schemas/Cat"
discriminator:
propertyName: pet_type
Pet:
type: object
required:
- pet_type
properties:
pet_type:
type: string
discriminator:
propertyName: pet_type
Dog: # "Dog" is a value for the pet_type property (the discriminator value)
allOf: # Combines the main `Pet` schema with `Dog`-specific properties
- $ref: '#/components/schemas/Pet'
- type: object
# all other properties specific to a `Dog`
properties:
bark:
type: boolean
breed:
type: string
enum: [Dingo, Husky, Retriever, Shepherd]
Cat: # "Cat" is a value for the pet_type property (the discriminator value)
allOf: # Combines the main `Pet` schema with `Cat`-specific properties
- $ref: '#/components/schemas/Pet'
- type: object
# all other properties specific to a `Cat`
properties:
hunts:
type: boolean
age:
type: integer
The classes I end up with essentially boil down to:
public class SinglePetResponse {
private @Valid Object pet = null;
}
and
public class AllPetsResponse extends ArrayList<Object> {
}
On top of that the "SinglePetResponse" is rendered as an empty object in the UI.
It is important for me to nest these properties under other objects - because in the real system the responses are much more than just a list of objects - they have other fields, too.
What I would like to see is the "Pet" class used instead of "Object" and a better rendering in the UI (a random type or just a first time would suffice). A nice, but not required property would be the Pet class being abstract.
Is there a way to achieve this with OpenAPI 3?
Best regards,
Alexey Nezhdanov