OpenAPITools / OpenAPITools/openapi-generator

[BUG] generator ignores format on objects

Open
#14,431 2 comments 2 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

According to the JSON Schema Specification Draft 2020-12, valid instance data models are null, boolean, object, array, number, and string. Furthermore, according to the openapi specification, all OAS datatypes are based on the types supported by the aforementioned specification, and can have an optional modifier property: format. The JSON Schema Specification defines several formats for datatypes, as does the openapi specification.

The generator supports additional format options via importMappings and typeMappings. However, when a schema identified as a type: object is defined, the format is ignored by the validator.

When using a custom format for a custom object, it should be defined as a type: object. This way tools such as Postman can properly validate a schema against a response (it will fail on format as unknown format, however this can be ignored so long as it matches the type of object. However, defining as a type: string will always cause schema validation tools to fail because the received object is not of type: string.

openapi-generator version

6.2.1

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: My-API
  version: 0.0.1
servers:
  - url: 'https://localhost:8080'
paths:
  /dates:
    get:
      operationId: getDates
      responses:
        "200":
          $ref: '#/components/responses/DateResponse'
        "5XX":
          description:  Unknown error has occured
      summary: get dates
      tags:
        - Dates
components:
  schemas:
    DateCollection:
      type: object
      properties:
        name:
          type: string
        objectDate:
          type: object
          format: instant
        stringInstant:
          type: string
          format: instant
        stringInstantRemappedDate:
          type: string
          format: date-time
  responses:
    DateResponse:
      description: OK
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DateCollection'

-->

Generation Details

I am using the gradle plugin. Using the above yaml, I run the generator with these settings.

    generatorName = "spring"
    inputSpec = "$projectDir/src/main/resources/static/object-format-example.yml"
    outputDir = "$projectDir"
    apiPackage = "com.generated.api.spring"
    invokerPackage = "com.generated.invoker.spring"
    modelPackage = "com.generated.model.spring"
    typeMappings = [
            OffsetDateTime: "Instant",
            instant: "Instant"
    ]
    importMappings = [
            Instant: "java.time.Instant"
    ]
    configOptions = [
            dateLibrary: "java8",
            serializableModel: "true"
    ]

The resulting generated model from the above configuration looks like this

  @JsonProperty("objectDate")
  private Object objectDate;

  @JsonProperty("stringInstant")
  private Instant stringInstant;

  @JsonProperty("stringInstantRemappedDate")
  @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
  private Instant stringInstantRemappedDate;
Steps to reproduce

Step 1. Use the yaml above
Step 2. Use the mappings above
Step 3. generate models

Related issues/PRs

None that I could find

Suggest a fix

Line 808 of the InlineModelResolver explicitly sets the format of an object model. However, the format is only used if the type is type: string.

Suggest updating the DefaultCodegen.java to allow models with a defined format to be processed similarly to strings. Specifically, these lines should be updated to the following:

        } else if (ModelUtils.isStringSchema(schema)) {
            if (typeMapping.containsKey(schema.getFormat())) {
                // If the format matches a typeMapping (supplied with the --typeMappings flag)
                // then treat the format as a primitive type.
                // This allows the typeMapping flag to add a new custom type which can then
                // be used in the format field.
                return schema.getFormat();
            }
            return "string";
        } else if (isFreeFormObject(schema)) {
            // Allows typeMapping flag to add a new custom type instead of an Object.
            // By defining a format for an object, objects can pass most schema validators
            // even if the format is unknown.
            if (typeMapping.containsKey(schema.getFormat())) {
                return schema.getFormat();
            }
            // Note: the value of a free-form object cannot be an arbitrary type. Per OAS specification,
            // it must be a map of string to values.
            return "object";

This would allow the schema to generate a custom object without defining a custom schema-mapping, and allow the schema to pass validation.

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 InlineModelResolver.java around line 808 and DefaultCodegen.java around line 2364, then reproduce the Gradle generation using the YAML and typeMappings in the issue. Compare the generated DateCollection model with the expected custom type for objectDate, while preserving the existing string-format behavior; done means object formats can use typeMappings without a schema-mapping.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi
Domain
backend-api-design, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.