OpenAPITools / OpenAPITools/openapi-generator

[BUG] Generator changes nested type to object when used in referenced file

Open
#9,818 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

When a schema references another schema as its property the property type is only correct in the generated code if the reference is defined in the base file

openapi-generator version

5.1.1

OpenAPI declaration file content or url

example is derived from https://swagger.io/docs/specification/data-models/data-types/ the Nested Objects section
i'm using the aspnetcore generator in the example but the behavior is them same using typescript-angular

Example 1:

index.yml


components:
  schemas:
    User:
        type: object
        properties:
          id:
            type: integer
          name:
            type: string
          contact_info:
            $ref: '#/components/schemas/ContactInfo'
    
    ContactInfo:
        type: object
        properties:
          email:
            type: string
            format: email
          phone:
            type: string

this produces the expected output


public class User : IEquatable<User>
{
   ...

    /// <summary>
    /// Gets or Sets ContactInfo
    /// </summary>
    [DataMember(Name="contact_info", EmitDefaultValue=false)]
    public ContactInfo ContactInfo { get; set; }
}

example 2:

index.yml


components:
  schemas:
    User:
        type: object
        properties:
          id:
            type: integer
          name:
            type: string
          contact_info:
            $ref: '#/components/schemas/ContactInfo'
    
    ContactInfo:
        $ref: './models/otherfile.yml#/components/schemas/ContactInfo

./models/otherfile.yml


components:
  schemas:
    ContactInfo:
      type: object
      properties:
        email:
          type: string
          format: email
        phone:
          type: string

this also produces the expected output


public class User : IEquatable<User>
{
   ...

    /// <summary>
    /// Gets or Sets ContactInfo
    /// </summary>
    [DataMember(Name="contact_info", EmitDefaultValue=false)]
    public ContactInfo ContactInfo { get; set; }
}

Example 3:

index.yml


components:
  schemas:
    User:
      $ref: './models/otherfile.yml#/components/schemas/User'
    ContactInfo:
      $ref: './models/otherfile.yml#/components/schemas/ContactInfo'

./models/otherfile.yml


components:
  schemas:
    User:
        type: object
        properties:
          id:
            type: integer
          name:
            type: string
          contact_info:
            $ref: '#/components/schemas/ContactInfo'
    
    ContactInfo:
        type: object
        properties:
          email:
            type: string
            format: email
          phone:
            type: string


public class User : IEquatable<User>
{
   ...

    /// <summary>
    /// Gets or Sets ContactInfo
    /// </summary>
    [DataMember(Name="contact_info", EmitDefaultValue=false)]
    public Object ContactInfo { get; set; }
}

In this case the ContactInfo property is typed as Object rather than 'ContactInfo'

Generation Details
{
  "$schema": "../../node_modules/@openapitools/openapi-generator-cli/config.schema.json",
  "spaces": 2,
  "generator-cli": {
    "version": "5.1.1",
    "generators": {
      "server": {
        "generatorName": "aspnetcore",
        "output": "#{cwd}/../.generated",
        "glob": "src/*.{json,yaml,yml}",
        "modelNameSuffix": "",
        "modelPackage": "MyComp.CommonData.Data",
        "apiNameSuffix": "Base",
        "apiPackage": "MyComp.CommonData",
        "additionalProperties": {
          "aspnetCoreVersion": "5.0",
          "packageName": "OpenApi.Generated",
          "classModifier": "abstract",
          "buildTarget": "library",
          "isLibrary": true,
          "operationIsAsync": true,
          "operationResultTask": true,
          "operationModifier": "abstract",
          "swashbuckleVersion": "5.0.0"
        }
      },
      "ng-client": {
        "generatorName": "typescript-angular",
        "glob": "src/*.{json,yaml,yml}",
        "output": "#{cwd}/../../.clients/ng",
        "additionalProperties": {
          "npmName": "@mycomp/ngclient-webservice-common-data",
          "npmVersion": "0.0.0",
          "npmRepository": "https://npm.pkg.github.com",
          "providedIn": "root",
          "serviceFileSuffix": ".api",
          "serviceSuffix": "Api"
        }
      }
    }
  }
}

Steps to reproduce

see examples

Related issues/PRs
Suggest a fix

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the index.yml and ./models/otherfile.yml examples, especially example 3, and reproduce the issue with the aspnetcore or typescript-angular generator using version 5.1.1. Compare the generated User.ContactInfo type with the expected ContactInfo type. Done means referenced nested schemas retain their named type when the schema is defined in another file.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, typescript
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.