swagger-ui icon indicating copy to clipboard operation
swagger-ui copied to clipboard

Multiple responses using oneOf attribute do not appear in UI

Open danr1979 opened this issue 7 years ago • 119 comments

Q A
Bug or feature request? Bug
Which Swagger/OpenAPI version?
Which Swagger-UI version?
How did you install Swagger-UI?
Which browser & version?
Which operating system?

Demonstration API definition

responses:
  '200':
    description: OK
    content:
      application/json:
        schema:
          oneOf:
            - $ref: '#/components/schemas/AuthorisationResponse'
            - $ref: '#/components/schemas/ForbiddenResponse'

Configuration (browser query string, constructor, config.yaml)

constructorConfig contains just the default values.

Expected Behavior

Since I have two schemas passed in as a $ref to the 200 response I would expect to see two schemas in the Swagger UI application.

Current Behavior

Instead I see only the reference to the 200 response and its description with no example responses displayed as JSON in the black boxes.

Possible Solution

Context

danr1979 avatar Oct 23 '17 13:10 danr1979

You've left out a bunch of details from the table - please fill them in.

We also need a full API definition - we can't really test the issue with the snippet you provided.

webron avatar Oct 23 '17 17:10 webron

The following spec shows nothing in the responses section of the UI - replacing the oneOf section with just an object containing either of the refs and it works fine.

Q A
Bug or feature request? Bug
Which Swagger/OpenAPI version? 3.0.0
Which Swagger-UI version? 3.4.2
How did you install Swagger-UI? CDN (Cloudflare)
Which browser & version? firefox 56/Chromium 62
Which operating system? Linux (Ubuntu 16.04.3
openapi: 3.0.0
info:
  contact:
    email: [email protected]
    name: No Name
  description: Example API
  version: 0.0.2
  title: example
paths:
  "/test":
    get:
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                oneOf:
                - "$ref": "#/definitions/foo"
                - "$ref": "#/definitions/bar"
definitions:
  foo:
    type: string
  bar:
    type: int

mrichar1 avatar Nov 03 '17 18:11 mrichar1

Similar issue occurs when using oneOf for a request body.

Q A
Bug or feature request? Bug
Which Swagger/OpenAPI version? 3.0.0
Which Swagger-UI version? which ever version is on editor.swagger.io
How did you install Swagger-UI? using editor.swagger.io
Which browser & version? Firefox 57.0
Which operating system? macOS 10.12.6
openapi: 3.0.0
info:
  title: Test API
  version: 0.0.1
servers:
  - url: 'localhost:3000/api'
    description: Local API URL.
paths:
  /test:
    get:
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/a'
                - $ref: '#/components/schemas/b'
      responses:
        '200':
          description: OK
components:
  schemas:
    a:
      type: integer
    b:
      type: string

zakini avatar Nov 20 '17 13:11 zakini

Hello,

I have the exact same problem and this issue still exists in version 3.5.

epetitje avatar Nov 27 '17 14:11 epetitje

I would be glad to see this implemented too. In the current state using multiple responses is not really usable because documentation consumer has to dig into YAML/JSON to find out all this information.

Oleg-Arkhipov avatar Dec 02 '17 18:12 Oleg-Arkhipov

@shockey I'm confused why this has been tagged as a Feature instead of Bug. According to the Specification, schema is listed as supporting anyOf, oneOf, and allOf.

crussell52 avatar Jan 08 '18 17:01 crussell52

Applying the oneOf to type within components/schema does not work around this problem.

components:
  responses:
    ...
    ServerWriteError:
      description: Write Failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ServerWriteErrorResponse'

  schemas:
    ...
    ServerWriteErrorResponse:
      oneOf:
        - $ref: '#/components/schemas/PartialWriteError'
        - $ref: '#/components/schemas/BaseError'

You can sort of work around this by declaring type: object as a sibling to oneOf:

components:
  responses:
    ...
    ServerWriteError:
      description: Write Failed
      content:
        application/json:
          schema:
            oneOf:
            $ref: '#/components/schemas/ServerWriteErrorResponse'

  schemas:
    ...
    ServerWriteErrorResponse:
      type: object     # Workaround-ish
      oneOf:
        - $ref: '#/components/schemas/PartialWriteError'
        - $ref: '#/components/schemas/BaseError'

OR In the referenced schema component

components:
 responses:
    ...
    ServerWriteError:
      description: Write Failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ServerWriteErrorResponse'

  schemas:
    ...
    ServerWriteErrorResponse:
      type: object
      oneOf:
        - $ref: '#/components/schemas/PartialWriteError'
        - $ref: '#/components/schemas/BaseError'

The work-around isn't great because it puts an empty object in the response example (which is shown by default), but at least consumers can see the relevant models: image

image

crussell52 avatar Jan 09 '18 15:01 crussell52

Hey @crussell52, I tagged it as a feature because Swagger-UI hasn't/doesn't support oneOf responses, as opposed to there being an issue with how a oneOf responses implementation renders things.

In other news... Work on this stalled (clearly), I'm going to do my best to circle back in January.

shockey avatar Jan 11 '18 00:01 shockey

@shockey That makes sense... thanks for the clarification :)

crussell52 avatar Jan 11 '18 01:01 crussell52

I am facing the same issue. Using oneOf in requestBody is fine. You can not see the exact example but can still see the model. User can dig inside.

However, responses not working. :) Just to share

vickysg0210 avatar Jan 24 '18 02:01 vickysg0210

i`m facing the same issue

JinSung-Hwang avatar Jan 25 '18 00:01 JinSung-Hwang

+1

jasongonzales23 avatar Feb 01 '18 02:02 jasongonzales23

@shockey I want to fix this issue. But I don't know how to do. There are two cases: 1.

schema: 
  type: array 
  items:  
    oneOf:  
      - type: string  
      - type: integer

I can do like this

image

schema:
  oneOf:
  - $ref: '#/components/schemas/a'
  - $ref: '#/components/schemas/b'

components:
  schemas:
    a:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    b:
      type: array
      items:
        type: integer
        format: int64

I can do like this image

Or something more complicated like in model tab? What do you think?

PavelStefanov avatar Feb 04 '18 10:02 PavelStefanov

i want the 2 type

JinSung-Hwang avatar Feb 05 '18 00:02 JinSung-Hwang

of those I prefer the second one. Since we can name examples in the yaml, would it be a stretch to have example1: text box

example2: text box

DustinOgan avatar Feb 12 '18 02:02 DustinOgan

@DustinOgan this is just two different case for oneOf attribute, for array and for object, and example like I can do.

PavelStefanov avatar Feb 12 '18 08:02 PavelStefanov

For arrays I like the approach to have one example of each item type in the example array. For objects, I think an approach like in the model tab seems appropriate to me.

NeoDobby avatar Feb 16 '18 09:02 NeoDobby

I too wish to see some way for Models to display oneOf. It is used in my OpenAPI document. It's not used in a particularly critical API endpoint, but thumbs-up to anybody working on a solution.

mikefidel avatar Feb 27 '18 17:02 mikefidel

@mikefidel Models in Swagger UI does display oneOf now. We just recently migrated our docs from swagger 2 to open api 3 just for that reason. See this help page: https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/

rickyblaha avatar Feb 27 '18 17:02 rickyblaha

@rickyblaha The spec supports it, but not the UI (unless you're saying bug has been resolved in the UI code?)

mrichar1 avatar Feb 27 '18 17:02 mrichar1

@mrichar1 this bug is not resolved (using oneOf for multiple responses), but reading Mike's post it looked like he was speaking of Models in general, which does work in the latest UI (e.g. a single response schema that refers to a component schema which uses oneOf or anyOf to refer to other component schemas.)

rickyblaha avatar Feb 27 '18 18:02 rickyblaha

For clarification: I was referring to Swagger-UI displaying the onOf alternate schemas in the Responses area as either an Example Value or Model or both.

Here is what Swagger-UI 3.11.0 displays and its associated OpenAPI 3.0 specification fragment. You'll see nothing displayed.

swagger-ui 3 11 0

openapi 3 0 spec

Again, this is not a hot issue for me -- just something that I wanted to go on record. Perhaps I added the comment into the wrong issue.

mikefidel avatar Feb 27 '18 20:02 mikefidel

What would you hope to see there?

webron avatar Feb 27 '18 21:02 webron

If I can add my 2c here, I think it would be nice to have a select component with all the possible models, and as each one is selected it can show the example and model in the same way. It gives the power to map multiple responses schemas and the user can inspect each one a time. The same could be said about request body, should I file another issue?

mgraciano avatar Mar 01 '18 15:03 mgraciano

The internet has been down all day due to a storm, and frankly I need a couple days to think through the problem. The eventual answer needs to cover oneOf and anyOf. It's possible that there exists schema that has nested oneOf and/or anyOf's -- that certainly makes the processing and UI exquisitely nasty. I need another day or two to think through and answer your simple question, @webron. I agree with @mgranciano's response and I suspect it is adequate for the lion's share of cases. However, I have not thought through the problem well enough to believe it works well when oneOf and/or anyOf's are nested at all depths of recursion. I'm new to React and Redux, but from what little I've learned it seems to be well suited to dealing with this sort of problem. Will get back to you in a couple days.

mikefidel avatar Mar 01 '18 23:03 mikefidel

After due consideration, I could not arrive at an acceptable UI. Of course, if the one assumes the api specification is: 1) simple 2) has relatively few such named attributes, and 3) doesn't nest oneOf's and/or anyOf's I did manage to come up with "on the back of the napkin" UX design that I think would be acceptable. It fell into the scenario @mgranciano describes or my simple oneOf schema. However my draft UX falls apart when oneOf itself includes an attribute containing another oneOf or anyOf (or visa-versa).

Just as a comment: I wonder if we could approach the solution differently. Perhaps the Example Value | Model can highlight that oneOf and/or anyOf applies by outputting a different styles color or background-color. Being alerted, the user can work through the implications. Just offering that as an idea.

mikefidel avatar Mar 05 '18 02:03 mikefidel

+1 this is something I would need in the UI

Fatflo avatar Mar 12 '18 20:03 Fatflo

For those of you who didn't notice, @PavelStefanov has submitted #3803 as a potential solution for this feature.

Everyone's input on this one has been great and much appreciated. Looks like @mikefidel managed to cover the major concerns I've been having all along. Let's try to summarize this and see how to proceed.

For clarity - this issue is relevant for OAS3 (and later) only.

The issue of displaying examples comes in several places:

  • Parameters (since they now support schema)
  • RequestBody (as a replacement to body parameters)
  • Responses
  • Headers (just like parameters)

While the two obvious places are responses and request body, we cannot ignore the other two places. The solution needs to fit all, otherwise we risk pushing the problem down the line.

The parameters and request bodies representation should also fit into the try-it-out functionality, meaning it should serve as an easy way to provide the input.

The issue also comes in two forms:

  • Generating examples when none are provided by the user (which is this ticket).
  • Displaying multiple examples when they are provided by the user (This is trying to be covered by #4092, which is based on #3616).

These two are related, because we would display one or the other, but not both. The experience should be similar as they serve the same purpose - showing an API consumer what they're expected to send/receive to/from the API.

anyOf and oneOf (and allOf for that matter) - aren't very meaningful when it comes to documentation (not functionality). We shouldn't assume that a consumer of the documentation automatically understands JSON Schema just because it's what the specification supports. The example in #4368 shows this problem exactly - it contains a oneOf of 4 items, but if you look at the generated examples, you'd notice that providing the last of the 4 as a value - it would actually fail, because it conflicts with the first one. This kind of distinction would be difficult on consumers to understand simply by seeing oneOf at the top of the examples. (for those of you who missed it - the last option would also validate against the first schema - this means it does not fit just one of the schemas and so it would fail validation. This wouldn't be the case with anyOf.) Similarly - allOf does not mean merge.

@mikefidel brought up the biggest issue that concerns me - having anyOf/oneOf deeper in definitions, and not just directly under scheme - that's where things get really nasty, and at the moment I'm not sure there's a clean solution to that.

It does seem that at the moment the majority of users is interested in supporting oneOf/anyOf at the root of the schema simply to be able to describe different basic input/output options. We could say that for the immediate future we'll try to add support for those cases and punt on supporting the deeper nested cases - I'm ok with that.

For input - I tend to favor either a tabbed view or a drop-down, where the user can choose which one they want to be displayed and served as a baseline for input. For output - we can go with either that or a flat view as proposed in the PR. The down side of a flat view is that it can make the UI very 'long'. On the other hand, it's easier to view all the information. The downside of a tabbed view is dealing with many examples that don't necessarily fit the view, and then you have another scroll-like feature to move between the different tabs.

It's a bit of a long summary, but I hope this has given you some insight into the challenges in supporting this feature. I'm sure any individual would love to see something that supports their use case, but it is our challenge, as project maintainers, to address the community as a whole. We'd appreciate your input and feedback on this based on the summary. I will try to get a UX person involved in this as well, but any additional input you may have will help.

webron avatar Apr 02 '18 10:04 webron

Excellent critique!

Tabbed or drop-down view: I have no particular preference regarding tabbed or drop-down views. My case may be unique, however the alternative data structures are relatively small -- perhaps 10-15 lines of code one way versus the other.

I thought more about the deeply nested alternative data structures. Perhaps the depth can be controlled through a configuration setting (oh yes... another one of those!). Make its default setting a reasonable recursion depth, yet allows the user to increase it if they have one of those nightmare schema we talked about. Decades ago, I wrote a programming language parser that had to cater for copy files within copy files within copy files -- and yet more copy files. It's amazing what people will code if given half the chance...

Keep up the good work!

mikefidel avatar Apr 06 '18 05:04 mikefidel

There is at least one case where nested anyOf/oneOf/allOf would be necessary or at least make it a lot easier to use swagger-ui without redesigning the schemas: anything based on JSON API. The JSON API JSON schema is at http://jsonapi.org/schema and includes plenty of these.

Dantemss avatar Apr 10 '18 22:04 Dantemss