Ok, lets step in of what we have and the issues we are currently facing....
We have a data model, pretty close to that what is available in other examples. (all code here in github: https://github.com/straube-jens/swagger)
We have a Basis DTO Class RsvXO (shitty Name, I know…) which has a List of Class Pet inside. Pet is an abstract Class and is implemented by Cat and Dog Class. Service Endpoint is delivering the basis class RsvXO. We put the Json Annotations for referencing the Classes Cat and Dog out of Pet.
We add the spring swagger-ui dependency to the pom and ran all that, to get the openapi description out of “swagger” generated.
Sure, there is documentation that writes that polymorphic is not covered by openapi which is actually not true for this example, but we will see later.
The generated description looks like the following example:
{
"openapi": "3.0.1",
"info": {
"title": "OpenAPI definition",
"version": "v0"
},
"servers": [
{
"url": "http://127.0.0.1:8080",
"description": "Generated server url"
}
],
"paths": {
"/vehicleDecision": {
"post": {
"tags": [
"rest-service"
],
"operationId": "createRiskDecission",
"parameters": [
{
"name": "rsvXO",
"in": "query",
"required": true,
"schema": {
"$ref": "#/components/schemas/RsvXO"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RsvXO"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Cat": {
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/Pet"
},
{
"type": "object",
"properties": {
"preferredGardenToPeeIn": {
"type": "string"
}
}
}
]
},
"Dog": {
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/Pet"
},
{
"type": "object",
"properties": {
"preferredPostman": {
"type": "string"
}
}
}
]
},
"Pet": {
"required": [
"petType"
],
"type": "object",
"properties": {
"name": {
"type": "string"
},
"petType": {
"type": "string"
}
},
"discriminator": {
"propertyName": "petType"
}
},
"RsvXO": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"pet": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/Cat"
},
{
"$ref": "#/components/schemas/Dog"
}
]
}
},
"aenderDatum": {
"type": "string",
"format": "date-time"
}
}
}
}
}
}
If we use the description on the client side to generate the data model, we get some wired implementation then. The generator is creating the Pet, the Dog and the Cat Classes as needed, that’s fine.
But is generates the for the Pet-relation in RsvXO another Class called RsvXOPetInner Class which is an exact copy of Pet. It sets the attribute inside the RsvXO to the type of RsvXOPetInner Class. But there is no relation to Pet Class in RsvXO or RsvXOPetInner.
So, it is technically not possible to set a Dog or a Cat instance inside the List in RsvXO, because the type of the Classes does not fit.
BUT
We changed the description json which was generated by the Server by hand. Available in the next post:
{
"openapi": "3.0.1",
"info": {
"title": "OpenAPI definition",
"version": "v0"
},
"servers": [
{
"url": "http://127.0.0.1:8080",
"description": "Generated server url"
}
],
"paths": {
"/vehicleDecision": {
"post": {
"tags": [
"rest-service"
],
"operationId": "createRiskDecission",
"parameters": [
{
"name": "rsvXO",
"in": "query",
"required": true,
"schema": {
"$ref": "#/components/schemas/RsvXO"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/RsvXO"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Cat": {
"required": [
"petType"
],
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/Pet"
}
],
"properties": {
"preferredGardenToPeeIn": {
"type": "string"
}
}
},
"Dog": {
"required": [
"petType"
],
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/Pet"
}
],
"properties": {
"preferredPostman": {
"type": "string"
}
}
},
"Pet": {
"oneOf": [
{
"$ref": "#/components/schemas/Cat"
},
{
"$ref": "#/components/schemas/Dog"
}
],
"required": [
"petType"
],
"type": "object",
"properties": {
"name": {
"type": "string"
},
"petType": {
"type": "string"
}
},
"discriminator": {
"propertyName": "petType"
}
},
"RsvXO": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"pet": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
"aenderDatum": {
"type": "string",
"format": "date-time"
}
}
}
}
}
}
If the client generator works over that json, the generated model looks perfect. So, there should actually be an option to build polymorphic data model structures with openapi, right?
Sure there is a ArraySchema and Schema Annotation from swagger, that we used as well, but the documentation (https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations) for that annotations does not cover our case.
We did the last 3 days a lot of try and error and decide now to ask the community for help.
So please check out the test-project from github (https://github.com/straube-jens/swagger) and hopefully you will have a solution or another hint for us.
Greetings and thanks a lot, Katrin and Jens