OpenAPITools / OpenAPITools/openapi-generator

[REQ] Extensible enums - how to model and generate

Open
#7,272 1 comment 13 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement: Feature
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Is your feature request related to a problem? Please describe.

This is a request for discussion that may lead to enhancements. How to model extensible enumerations in OpenAPI doc and how to generate client SDKs? Specifically how to generate clients that don't cause exceptions when new enums are added in the OpenAPI documents at a later date?

Suppose an OpenAPI doc has a property which is an enum type, for example:

components:
  schemas:
     Person:
       properties:
         emotion:
           type: string
           enum:
           - joy
           - surprise
           - trust
           - disgust

Also, suppose other enums are added to the OpenAPI doc at a later date, e.g. sadness and fear. When the server is upgraded and supports a new enum, many things can happen.

If all clients are updated based on the new OpenAPI doc (with the new enums), no problem will occur. I.e. all clients will be able to unmarshal a server response payload that contains the new enum values (sadness and fear).

However, in practice it's unlikely all clients will be updated at the same time, especially if the clients are controlled by different organizations (e.g. the server is a SaaS service). The client behavior depends on how the specific code generator (python, go, java...).

  1. Some generated clients have strict validation and raise an unmarshaling exception because the enum is not in the list of supported values. Therefore the client cannot manipulate a server payload that contains the new enum value. For example the client is able to unmarshal joy because it was there in the original OpenAPI doc, but it will fail if it receives sadness. That can lead to unhappy customers who complain every time a new enum is added, that breaks their client.
  2. Some generated clients are lenient and will unmarshal the payload. For example, they may store the new enum in a field of type string. This does not necessarily guarantee the client will be able to process the data, but if the behavior is document ahead of time, the application logic can handle these values gracefully.
  3. Some clients can be configured to be lenient or strict.

The backward compatibility challenges are not limited to enums. For example, suppose server v1 supports up to 3 items in a list, then it may specify minItems: 3 in the OpenAPI doc. But later that restriction is relaxed and the server supports up to 6 items in a list.

Describe the solution you'd like

Solution 1 would be to change the major version of the OpenAPI doc every single time a new enum value is added. This solves the problem, but IMO it's also very cumbersome in practice. If the OpenAPI doc has lots of enum, the major version must change every time a new enum is added. Also, that complicates the server-side because the server must now support many API major versions. Also, what happens if an older client performs a GET request? What value should the server return?

Solution 2 would be to remove the enums. to plan for the future extensions. i.e. don't specify enum so the property can have any value. The downside is we lose the explicit list of known enums, so there is no documentation and no client-side validation.

components:
  schemas:
     Person:
       properties:
         emotion:
           type: string

Solution 3 would be to add a placeholder for future values in the OpenAPI document with the use of anyOf. That kinda works, though a client needs to know they shouldn't set arbitrary values, only known values. I also feel it's "not right" because it does not really describe what the API expects.

components:
  schemas:
     Person:
       properties:
         emotion:
           anyOf:
           - type: string
             description: list of known values.
             enum:
             - joy
             - surprise
             - trust
             - disgust
           - type: string
              description: placeholder for future values.

Describe alternatives you've considered

Additional context

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

This is an unresolved design discussion about modeling extensible enums and generating clients across Python, Go, and Java. No repository files, tests, or entry points are identified. Work would first require reaching agreement on the OpenAPI representation and the expected strict or lenient client behavior, then defining tests for the chosen approach.

Written by the indexing model from the issue text.

Assessment

Tech stack
openapi
Domain
api, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.