Search code examples
javaswaggeropenapiopenapi-generator

openAPI polymorphism - getting generated file to extend another schema


so im pretty new to openAPI and trying to get one schema to extend another. I have it working to a certain extent in that I have two objects, a vehicle and a car (which should extend the vehicle object). When these files are generated using openAPI generator I can see that the car object does infact have the properties of the vehicle object. However, these values have been added to the class as opposed to the car object being extended from the vehicle object. Is there any way that one object can be an extention of another object when the classes are auto generated?

OpenAPI spec for the schemas:

vehicle:
  type: object
  properties:
    vehicleProperty:
      type: string
      description: "property for vehicle"

car:
  type: object
  oneOf:
    - $ref: '#/components/schemas/vehicle'
    - type: object
  properties:
    carProperty:
      type: string
      description: "property for car"

Auto generated files: Vehicle file:

public class Vehicle  implements Serializable {

private static final long serialVersionUID = 1L;

@JsonProperty("vehicleProperty")
private String vehicleProperty;

public Vehicle vehicleProperty(String vehicleProperty) {
  this.vehicleProperty = vehicleProperty;
  return this;
}
....

Car file

public class Car  implements Serializable {

private static final long serialVersionUID = 1L;

 @JsonProperty("carProperty")
 private String carProperty;

 @JsonProperty("vehicleProperty")
 private String vehicleProperty;
 ....

As you can see, the car file has got the vehicle property but it isnt generated as an extention of the vehicle. Is there any way to acheive this?

Any help would be greatly appreciated, Thanks.


Solution

  • If you want to achieve polymorphism you shouldn't use oneOf but allOf. After all, you want both the parent class and your own properties:

    car:
      allOf:
        - $ref: '#/components/schemas/vehicle'
        - type: object    
          properties:
            carProperty:
              type: string
              description: "property for car"
    

    That's not enough though, you need to tell the generator to include the parent/child structure. This can be done by setting the OpenAPI Normalizer to REF_AS_PARENT_IN_ALLOF=true. When using the openapi-generator-maven-plugin you can do this by adding the following to the plugin's configuration:

    <openapiNormalizer>REF_AS_PARENT_IN_ALLOF=true</openapiNormalizer>
    

    The result with the jaxrs-spec generator:

    @JsonTypeName("car")
    @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen", date = "2023-09-16T13:44:47.665859200+02:00[Europe/Amsterdam]")
    public class Car extends Vehicle  {
    ...
    }
    

    Note that you can't make full use of any generated fluent API though; Car does not override any property-specific methods, so the only methods you have to set the vehicleType are:

    • public Vehicle vehicleProperty(String vehicleProperty)
    • public void setVehicleProperty(String vehicleProperty)

    Because the first one returns Vehicle and is not overridden, you cannot do this:

    Car car1 = new Car()
            .carProperty("...")
            .vehicleProperty("..."); // cannot assign Vehicle to Car
    Car car2 = new Car()
            .vehicleProperty("...")
            .carProperty("..."); // method not defined for Vehicle