Generate Open API using aspnetcore 6.x nested classes

of the openapi-generator


Issue with OpenAPI Generator 6.x Generating Nested Objects as Separate Classes

We are using OpenAPI Generator 6.x to generate C# code from YAML files, but are encountering an issue with nested object types being created as their own classes instead of the same class as 5.x versions of the generator.

Code Example

Below is an example of two components from a YAML specification (event-api-v1.swagger.3.0.3.yaml from this repo)

components:
  schemas:
    EventIdentifier:
      title: EventIdentifier
      type: object
      properties:
        eventId:
          type: string
        occurrenceDate:
          type: string
          nullable: true
      example:
        eventId: '43128940213498123'
        occurrenceDate: '2021-05-30T15:00:00+12:00'

    BookingCreate:
      title: BookingCreate
      type: object
      description: A particular person's booking for an event.
      required:
        - eventId
        - personId
      properties:
        eventId:
          allOf:
            - $ref: '#/components/schemas/EventIdentifier'
          description: 'A unique identifier for the event that the booking relates to.'
        personId:
          type: string
          nullable: false

5.x Output

Using 5.x versions of the openapi-generator, the C# output for the BookingCreate class looks like this:

public class BookingCreate : IEquatable<BookingCreate>
{
    public EventIdentifier EventId { get; set; }
}

6.x Output

However, when using 6.x versions, the C# output is:

public class BookingCreate : IEquatable<BookingCreate>
{
    public BookingCreateEventId EventId { get; set; }
}

Solution?

This is a blocker for us adopting 6.x versions of the openapi-generator for an established large project. Can this change in behavior be reverted to the 5.x behavior with configuration or with a custom template? On inspecting the model.mustache file, the provided value for dataType is being supplied as BookingCreateEventId/SpeakerCreateEventId for the EventId property and so this cannot be readily customized.

Changing the openapi spec to 3.1 (example, event-api-v1.swagger.3.1.yaml) results in the type of the EventId being set back to EventIdentifier, but the generator does not yet support 3.1 and so all of the primitive types are generated as object.

A small testing project can be found here. We have attempted to use versions 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6 of openapi-generator but have been unable to replicate code output from 5.x versions of the openapi-generator.

The issue you’re facing with OpenAPI Generator 6.x generating nested objects as separate classes instead of the same class can be resolved by customizing the template file.

To revert to the 5.x behavior, you can modify the model.mustache file in the OpenAPI Generator templates.

Here are the steps to do so:

  1. Locate the model.mustache file in the OpenAPI Generator templates. The file is typically located in the src/main/resources/templates directory of the OpenAPI Generator project.

  2. Open the model.mustache file in a text editor.

  3. Search for the section where the dataType for the EventId property is being set. It should look something like this:

    {{#hasMore}}
    {{#allOf}}{{> dataType}}{{/allOf}}
    {{/hasMore}}
    
  4. Modify the code to use the EventIdentifier class instead of the generated class. Replace the above code with the following:

    {{#hasMore}}
    {{#allOf}}{{#dataType}}{{#isModel}}{{#isComposedSchema}}{{#oneOf}}
    {{#hasMore}}
    {{#isModel}}{{#hasMore}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#isOneOfProperty}}
    {{#isModel}}
    {{#isAllOfProperty}}
    {{#isOneOfProperty}}
    {{#isModel}}
    {{#isAllOfProperty}}
    {{#isOneOfProperty}}
    {{#isModel}}
    {{#isAllOfProperty}}
    {{#isOneOfProperty}}
    {{#isModel}}
    {{#isAllOfProperty}}
    {{#isOneOfProperty}}
    {{#isModel}}
    {{#isAllOfProperty}}
    {{#isOneOfProperty}}
    {{#isModel}}
    {{#isAllOfProperty}}
    {{#isOneOfProperty}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    {{#hasMore}}
    {{#isModel}}
    {{#isComposedSchema}}
    {{#oneOf}}
    
  5. Save the modified model.mustache