1

I've created a specification that has objects with enum values. Some methods should support all enum values and therefore I thought just to put the enum objects as allOf reference, however that doesn't seems to be working.

In the example below the EnumObject class doesn't contain any values, while the EnumObjectA and EnumObjectB are working as expected.

openapi: 3.0.3
info:
    title: Test spec for StackOverflow
    version: 1.0.0
paths:
    /status:
        get:
            tags:
                - Test
            summary: Test summary
            description: 'Test description'
            operationId: testOperationId
            responses:
                '200':
                    description: Successful operation
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/TestResponse'
components:
    schemas:
        TestResponse:
            type: object
            properties:
                stringId:
                    type: string
                enumObject:
                    $ref: '#/components/schemas/EnumObject'
        EnumObject:
            allOf:
                - $ref: '#/components/schemas/EnumObjectA'
                - $ref: '#/components/schemas/EnumObjectB'
        EnumObjectA:
            type: string
            description: Enum object A
            enum:
                - VALUE_A1
                - VALUE_A2
        EnumObjectB:
            type: string
            description: Enum object B
            enum:
                - VALUE_B1
                - VALUE_B2
                - VALUE_B3

I'm using the following configuration within the openapi-generator-maven-plugin. If this feature not supported or am I missing something?

<configuration>
    <inputSpec>${project.basedir}/src/main/resources/openapi/rest.yaml</inputSpec>
    <generatorName>jaxrs-spec</generatorName>

    <configOptions>
        <dateLibrary>java8</dateLibrary>
        <interfaceOnly>true</interfaceOnly>
        <useTags>true</useTags>
    </configOptions>

    <generateApiTests>false</generateApiTests>
    <generateApiDocumentation>false</generateApiDocumentation>
    <generateModelTests>false</generateModelTests>
    <generateModelDocumentation>false</generateModelDocumentation>
    <generateSupportingFiles>false</generateSupportingFiles>
    <ignoreFileOverride>${project.basedir}/src/main/resources/.openapi-codegen-ignore</ignoreFileOverride>
</configuration>
Danny Gloudemans
  • 2,597
  • 7
  • 39
  • 57

1 Answers1

1

The short answer to your question is that this feature is indeed not supported. Another post suggests using oneOf as an alternative, but this doesn't really work with the generator as you are expecting it to.

However, I'm never one to shy away from a challenge. So, if you are interested in a fun workaround, read on.


This issue can be solved with some clever templating, or more specifically, the use of vendor-extensions.

One of the key issues here is that the generator does not recognize the EnumObject as an enum. Despite it's inheritence, the class created is a regular class, and not an enum class. So, when the generator enters the model.mustache and makes a decision as to whether the class should be an enum or a regular class, it decides to create a regular class. So, let's fix that with a vendor extension called x-is-composite-enum.

Define your enum object like this

EnumObject:
  allOf:
    - $ref: '#/components/schemas/EnumObjectA'
    - $ref: '#/components/schemas/EnumObjectB'
  x-is-composite-enum: true

Now, add a templates folder to your maven configuration.

<configOptions>
  <templateDirectory>"$projectDir/src/main/resources/templates"</templateDirectory>
</configOptions>

and copy the model.mustache template into that folder.

Now change line 18 of the template from {{^isEnum}}{{>pojo}}{{/isEnum}} to the following:

{{^isEnum}}{{#vendorExtensions.x-is-composite-enum}}{{>composite_enum}}{{/vendorExtensions.x-is-composite-enum}}{{^vendorExtensions.x-is-composite-enum}}{{>pojo}}{{/vendorExtensions.x-is-composite-enum}}{{/isEnum}}

What this does is checks for the vendor extension we created above. If that extension exists, it tells the generator to generate the model using the composite_enum.mustache template. If not, then generate a pojo as normal.

But, currently composite_enum.mustache doesn't exist. No worries, let's create it.

Simply copy the enumOuterClass.mustache template to your templates folder, and rename it to composite_enum.mustache

Finally, change line 17 and 18 of the file from this:

  {{^gson}}
  {{#allowableValues}}{{#enumVars}}
  {{{name}}}({{{value}}}){{^-last}},
  {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}}
  {{/gson}}

to this

  {{^gson}}
  {{#composedSchemas}}{{#allOf}}{{#.}}{{#allowableValues}}{{#values}}
  {{{.}}}({{{.}}}){{^-last}},{{/-last}}{{/values}}{{/allowableValues}}{{^-last}},{{/-last}}{{/.}}{{#-last}};{{/-last}}{{/allOf}}{{/composedSchemas}}
  {{/gson}}

The newly generated object will now have all your enums

public enum EnumObject {
  
  VALUE_A1(VALUE_A1),
  VALUE_A2(VALUE_A2),
  VALUE_B1(VALUE_B1),
  VALUE_B2(VALUE_B2),
  VALUE_B3(VALUE_B3);

  private EnumObjectA value;
tbatch
  • 1,398
  • 10
  • 21