Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REQ] Extensible enums - how to model and generate #7272

Open
sebastien-rosset opened this issue Aug 23, 2020 · 0 comments
Open

[REQ] Extensible enums - how to model and generate #7272

sebastien-rosset opened this issue Aug 23, 2020 · 0 comments

Comments

@sebastien-rosset
Copy link
Contributor

sebastien-rosset commented Aug 23, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant