-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Composition/Inheritance/Polymorphism issues (v2.0.6) #3046
Comments
I have a work-around for this using To get rid of the extraneous "type" property I added an I've read a lot of confused posts about this out there so maybe an 'official' example/test case might be a good idea? |
One way to achieve what you need with annotations would be the following: @GET
@Path("/random")
@Produces(MediaType.APPLICATION_JSON)
public Pet random() {
Random rand = new Random();
if (rand.nextBoolean())
return new Cat(rand.nextBoolean());
else
return new Dog(rand.nextBoolean());
}
@Schema(
type = "object",
title = "Pet",
subTypes = { Cat.class, Dog.class },
discriminatorMapping = {
@DiscriminatorMapping( value = "CAT", schema = Cat.class ),
@DiscriminatorMapping( value = "DOG", schema = Dog.class )
},
discriminatorProperty = "petTypeAsString"
)
public class Pet {
public enum PetType {
CAT,
DOG;
}
@Schema(required = true)
public PetType petType;
@Schema(required = true)
public String petTypeAsString;
public Pet() {
}
public Pet(PetType petType) {
this.petType = petType;
this.petTypeAsString = petType.name();
}
}
public class Cat extends Pet{
public boolean hunts;
public Cat() {
super(Pet.PetType.CAT);
}
public Cat(boolean hunts) {
this();
this.hunts = hunts;
}
}
public class Dog extends Pet{
public boolean barks;
public Dog() {
super(Pet.PetType.DOG);
}
public Dog(boolean barks) {
this();
this.barks = barks;
}
} which would result to the following spec: openapi: 3.0.1
paths:
/pets/cat:
get:
summary: Generate a cat
operationId: cat
responses:
default:
description: a cat
content:
application/json:
schema:
$ref: '#/components/schemas/Cat'
/pets/random:
get:
summary: Generate a pet
operationId: random
responses:
default:
description: a pet
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
components:
schemas:
Cat:
required:
- petType
- petTypeAsString
type: object
properties:
hunts:
type: boolean
allOf:
- $ref: '#/components/schemas/Pet'
Dog:
required:
- petType
- petTypeAsString
type: object
properties:
barks:
type: boolean
allOf:
- $ref: '#/components/schemas/Pet'
Pet:
title: Pet
required:
- petType
- petTypeAsString
type: object
properties:
petType:
type: string
enum:
- CAT
- DOG
petTypeAsString:
type: string
discriminator:
propertyName: petTypeAsString
mapping:
CAT: '#/components/schemas/Cat'
DOG: '#/components/schemas/Dog' |
Hey,
Which is clearly wrong. I'm useing springdoc-openapi 1.6.6 I already wrote an issue to springdoc-openapi with examples, hoping it's their problem and they will fix it, but they said it's not an issue on their part (and just referenced another issue that is somewhat related, but not). |
Example is still valid with latest version: package io.swagger.v3.jaxrs2.resources;
import io.swagger.v3.oas.annotations.media.DiscriminatorMapping;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.Random;
@Path("/test")
public class DiscriminatorResource {
@GET
@Path("/random")
@Produces(MediaType.APPLICATION_JSON)
public Pet random() {
Random rand = new Random();
if (rand.nextBoolean())
return new Cat(rand.nextBoolean());
else
return new Dog(rand.nextBoolean());
}
@Schema(
type = "object",
title = "Pet",
subTypes = {Cat.class, Dog.class},
discriminatorMapping = {
@DiscriminatorMapping(value = "CAT", schema = Cat.class),
@DiscriminatorMapping(value = "DOG", schema = Dog.class)
},
discriminatorProperty = "petTypeAsString"
)
static class Pet {
public enum PetType {
CAT,
DOG;
}
@Schema(required = true)
public PetType petType;
@Schema(required = true)
public String petTypeAsString;
public Pet() {
}
public Pet(PetType petType) {
this.petType = petType;
this.petTypeAsString = petType.name();
}
}
static class Cat extends Pet {
public boolean hunts;
public Cat() {
super(Pet.PetType.CAT);
}
public Cat(boolean hunts) {
this();
this.hunts = hunts;
}
}
static class Dog extends Pet {
public boolean barks;
public Dog() {
super(Pet.PetType.DOG);
}
public Dog(boolean barks) {
this();
this.barks = barks;
}
}
} resolves into: openapi: 3.0.1
paths:
/upload/random:
get:
operationId: random
responses:
default:
description: default response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
components:
schemas:
Cat:
required:
- petType
- petTypeAsString
type: object
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
hunts:
type: boolean
Dog:
required:
- petType
- petTypeAsString
type: object
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
barks:
type: boolean
Pet:
title: Pet
required:
- petType
- petTypeAsString
type: object
properties:
petType:
type: string
enum:
- CAT
- DOG
petTypeAsString:
type: string
discriminator:
propertyName: petTypeAsString
mapping:
CAT: '#/components/schemas/Cat'
DOG: '#/components/schemas/Dog'
|
is it possible to do it with an interface? @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) |
I'm trying to build an API where some responses can be one of many sub-classes.
In this simple toy API, the "GET /pets/random" is to return one Pet which could be either a Cat or a Dog.
So the Java function PetResource.random() returns Pet.
The "discrimination" property is a member of the parent Pet class.
However, the JSON output only ever reports properties from the parent Pet class:
when I'm expecting
I've tried various ways of annotating both PetResource, Pet and the Cat/Dog sub-classes to no avail.
In addition to this, there's a simpler "GET /pets/cat" which returns (one) Cat but also an extraneous field "type" which I can't seem to locate/remove:
Two (related) bugs here? Or what am I doing wrong?
Can't seem to attach Java files so...
PetResource.java:
Pet.java:
Cat.java:
Dog.java:
The text was updated successfully, but these errors were encountered: