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

oneOf containing only a single enum (or ref to one) does not display as drop-down #7912

Closed
hauntingEcho opened this issue Mar 15, 2022 · 9 comments

Comments

@hauntingEcho
Copy link

Q&A (please complete the following information)

  • OS: Windows 10
  • Browser: Firefox
  • Version: 98.0.1 (64-bit)
  • Method of installation: dist assets
  • Swagger-UI version: 4.5.0
  • Swagger/OpenAPI version: OpenAPI 3.0.0

Content & configuration

Dist assets with the below YAML, running on an S3 bucket with website config enabled.

Example Swagger/OpenAPI definition:

openapi: 3.0.0
paths:
  /1:
    get:
      parameters:
      - name: order
        in: query
        description: Optional parameter for the method to sort results by.
        schema:
          default: Ascending
          oneOf:
          - $ref: '#/components/schemas/SortOrder'
  /2:
    get:
      parameters:
      - name: order
        in: query
        description: Optional parameter for the method to sort results by.
        schema:
          $ref: '#/components/schemas/SortOrder'
  /3:
    get:
      parameters:
      - name: order
        in: query
        description: Optional parameter for the method to sort results by.
        schema:
          type: string
          enum:
          - ascending
          - descending
  /4:
    get:
      parameters:
      - name: order
        in: query
        description: Optional parameter for the method to sort results by.
        schema:
          $ref: '#/components/schemas/SortOrder'
  /5:
    get:
      parameters:
      - name: order
        in: query
        description: Optional parameter for the method to sort results by.
        schema:
          type: string
          nullable: true
          enum:
          - ascending
          - descending
  /6:
    get:
      parameters:
      - name: order
        in: query
        description: Optional parameter for the method to sort results by.
        schema:
          oneOf:
          - type: string
            enum:
            - ascending
            - descending
components:
  schemas:
    SortOrder:
      type: string
      enum:
      - ascending
      - descending
    NullableSortOrder:
      type: string
      nullable: true
      enum:
      - ascending
      - descending

Swagger-UI configuration options:

I'm using the plain HTML/JS distribution, only changing the URL to be relative:

      const ui = SwaggerUIBundle({
        url: "openapi.yaml",
        dom_id: '#swagger-ui',
        deepLinking: true,
        presets: [
          SwaggerUIBundle.presets.apis,
          SwaggerUIStandalonePreset
        ],
        plugins: [
          SwaggerUIBundle.plugins.DownloadUrl
        ],
        layout: "StandaloneLayout"
      });

Describe the bug you're encountering

All six endpoints above should display with dropdowns for their enumeration values. /1 and /6 display with text boxes instead.

To reproduce...

Steps to reproduce the behavior:

  1. Host the static dist files with the above YAML
  2. scroll to each endpoint and see their prompt for order.

Expected behavior

All six endpoints displayed identically

Screenshots

image

@hauntingEcho
Copy link
Author

This is needed to have defaults/descriptions/examples/etc defined at the endpoint level, while using a shared definition for the enum.

@hauntingEcho
Copy link
Author

From further experimentation, this also affects anyOf, but not allOf

@mbsanchez01
Copy link

I have the same issue using oneOf

@bnowak
Copy link

bnowak commented Mar 4, 2024

hello @hauntingEcho

I try to solve partially-related topic about nullable enums (described here) and the core issue is around using allOf/oneOf.

Could you explain why do you need to wrap enum refs with oneOf at all? As far I understood the topic, you need to have shared definition which you want to decorate with some properties but only for specific usage (like adding default value for specific endpoint) - is that correct?

If yes, why not use allOf which combines a few types to singe one, something like this:

schema:
    allOf:
        - $ref: '#/components/schemas/SortOrder'
        - default: Ascending

would it work for your case?

@hauntingEcho
Copy link
Author

hauntingEcho commented Mar 4, 2024

Hi @bnowak , the OpenAPI files which led me to open this issue were generated from code via the C# library NSwag, although my sample file was manually written. This was at a previous job, so I don't still have access to the relevant source to poke at.

@mbsanchez01
Copy link

mbsanchez01 commented Mar 5, 2024

I don't know what is the specific use case for @hauntingEcho, but in my case, I want to generate some query filter parameters to my spec, in order to use queries with eq, neq, in, etc. or just the field. So using the example above I have

openapi: 3.0.0
paths:
  /api/question-options:
    get:
      operationId: QuestionOptionsController_findAll
      parameters:
        - name: status
          required: false
          in: query
          style: deepObject
          explode: true
          schema:
            oneOf:
              - type: string
                enum:
                  - active
                  - archived
              - type: object
                properties:
                  eq:
                    type: string
                    enum:
                      - active
                      - archived
                  neq:
                    type: string
                    enum:
                      - active
                      - archived
                  in:
                    type: array
                    items:
                      type: string
                      enum:
                        - active
                        - archived
                  notIn:
                    type: array
                    items:
                      type: string
                      enum:
                        - active
                        - archived

@bnowak
Copy link

bnowak commented Mar 5, 2024

@mbsanchez01 yeah, your case looks on different and more complex one. The spec looks to be correct.

However, I'm not sure swagger-ui is able (and whether should be in fact) to determine such complex schema compositions and render drop-downs for instance.

If there's oneOf with only single children, it could be brought to this single type as there no other oneOf case. Like, kind of simplicity, but IMO such cases shouldn't be wrapped with oneOf at all - it doesn't bring any additional value, but make the spec only more complex.

On your example, what would be expectation to render field which can have multiple types/values and be object as well?

All of that doesn't mean the spec is not correct and API endpoint couldn't be used as expected with passing all defined sub schemas

@mbsanchez01
Copy link

I don't expect swagger-ui to handle a complex case like that, I just expect it to use the first children of the oneOf to build the UI, in this case, I expect it to show something like in this image and not just a textfield

image

@char0n
Copy link
Member

char0n commented May 14, 2024

Hi everybody,

This issue has been addressed in #9934

More info in: #9934 (comment)

glowcloud added a commit that referenced this issue May 14, 2024
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

5 participants