Forum Discussion

didier's avatar
didier
Frequent Visitor
5 years ago

Using inheritance and having both base type and subtypes in endpoints breaks the object hierarchy

Hi all, I'm using swagger 2.1.0 to annotate my JAX-RS ressources and to generate the openAPI documentation. I'm facing a problem with inheritance. In order to expose the situation we can take the Pet example from the openAPI specification. I implemented it as follows in java with jackson annotations:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({ 
	@Type(value = Cat.class), 
	@Type(value = Dog.class) 
})
public class Pet {

	private String name;

	public final String getName() {
		return name;
	}
	public final void setName(String name) {
		this.name = name;
	}
}
public class Cat extends Pet {

	public enum HuntingSkill { clueless, lazy, adventurous, aggressive};
	
	private HuntingSkill huntingSkill;
	
	public final HuntingSkill getHuntingSkill() {
		return huntingSkill;
	}
	public final void setHuntingSkill(HuntingSkill huntingSkill) {
		this.huntingSkill = huntingSkill;
	}
}
public class Dog extends Pet {

	private int packSize;
	
	public final int getPackSize() {
		return packSize;
	}
	public final void setPackSize(int packSize) {
		this.packSize = packSize;
	}
}

and I define the following two Endpoints in a JAX-RS resource:

@Path("/")
public final class SwaggerTestRS {
	
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/pet/{name}")
	@Operation(
		summary = "Gets the pet having the given name", 
		responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Pet.class)))
	)
	public Response getPet(
			@PathParam("name")
			String name) {
		return Response.ok().build();
	}
	
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/pet/cat/{name}")
	@Operation(
		summary = "Gets the cat having the given name", 
		responses = @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Cat.class)))
	)
	public Response getCat(
			@PathParam("name")
			String name) {
		return Response.ok().build();
	}
}

The endpoint getPet() is defined to return a Pet and getCat() a Cat. Out of this api the following openAPI documentation gets generated:

openapi: 3.0.1
paths:
  /pet/{name}:
    get:
      summary: Gets the pet having the given name
      operationId: getPet
      parameters:
      - name: name
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
  /pet/cat/{name}:
    get:
      summary: Gets the cat having the given name
      operationId: getCat
      parameters:
      - name: name
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cat'
components:
  schemas:
    Cat:
      type: object
      properties:
        name:
          type: string
        huntingSkill:
          type: string
          enum:
          - clueless
          - lazy
          - adventurous
          - aggressive
    Dog:
      type: object
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        properties:
          packSize:
            type: integer
            format: int32
    Pet:
      required:
      - type
      type: object
      properties:
        name:
          type: string
        type:
          type: string
      discriminator:
        propertyName: 

Dog does inherit from Pet with the "allOf" definition, cat on the other hand does not. So Cat is no more a Pet and is no more an acceptable return type for the getPet() endpoint.

By removing the getCat() endpoint, the openApi documentation is generated as I would expect, with both Dog and Cat "extending" Pet.

Is this the expected behaviour or might it be a bug?

Thank you very much for your thoughs and maybe workarounds!

 

 

No RepliesBe the first to reply