swagger-api / swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.
https://swagger.io
Apache License 2.0
26.55k stars 8.96k forks source link

Multiple responses using oneOf attribute do not appear in UI #3803

Open danr1979 opened 7 years ago

danr1979 commented 7 years ago
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

webron commented 7 years ago

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.

mrichar1 commented 7 years ago

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: none@example.com
    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
zakini commented 6 years ago

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
epetitje commented 6 years ago

Hello,

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

Oleg-Arkhipov commented 6 years ago

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.

crussell52 commented 6 years ago

@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 commented 6 years ago

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

shockey commented 6 years ago

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.

crussell52 commented 6 years ago

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

vickysg0210 commented 6 years ago

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

JinSung-Hwang commented 6 years ago

i`m facing the same issue

jasongonzales23 commented 6 years ago

+1

PavelStefanov commented 6 years ago

@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

2.

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?

JinSung-Hwang commented 6 years ago

i want the 2 type

DustinOgan commented 6 years ago

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

PavelStefanov commented 6 years ago

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

NeoDobby commented 6 years ago

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.

mikefidel commented 6 years ago

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.

rickyblaha commented 6 years ago

@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/

mrichar1 commented 6 years ago

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

rickyblaha commented 6 years ago

@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.)

mikefidel commented 6 years ago

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.

webron commented 6 years ago

What would you hope to see there?

mgraciano commented 6 years ago

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?

mikefidel commented 6 years ago

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 commented 6 years ago

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.

Fatflo commented 6 years ago

+1 this is something I would need in the UI

webron commented 6 years ago

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:

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:

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.

mikefidel commented 6 years ago

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!

Dantemss commented 6 years ago

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.

kritika0205 commented 6 years ago

And update on this as of now? I still cannot see my oneOf in the Swagger UI example/model,.

cmavromoustakos commented 6 years ago

Same here. This is a blocker for us as we are sending these docs for our api to a customer and they can not display them properly.

swagger_editor
ilnurshax commented 6 years ago

+1 Today I also approached the need for this function. :)

sknuell commented 6 years ago

+1

PavelStefanov commented 6 years ago

Guys I want to suggest you try to use examples as workaround

content: 
  application/json: 
    schema: 
      anyOf: 
        - $ref: '#/components/schemas/Jessica' 
        - $ref: '#/components/schemas/Ron'
 examples: 
  Jessica: 
    value: 
      id: 10 
      name: Jessica Smith 
  Ron: 
    value: 
      id: 20 
      name: Ron Stewart 
webron commented 6 years ago

Everyone - asking whether it's already implemented or adding +1 comments is not helpful. If we haven't updated that it's implemented, then it's not been implemented, no need to ask. +1'ing just adds more notifications - you can use the reaction feature on the top comment to +1 and show us that this is important to you.

Nobody saying this is not important - however, there are real issues implementing support for it and until we resolve those there's nothing to implement. If you have any thoughts on how to address the concerns (and they are all written above), feel free to join the conversation. However, don't expect us to make a solution that works for you if it's "good enough", but doesn't address the issues as a whole. We're not going to replace one issue with a set of others.

dgrahn commented 6 years ago

@PavelStefanov

Illl add to your example with the following, if you are switching between schemas based on a parameter.

content: 
  application/json: 
    schema: 
      anyOf: 
        - $ref: '#/components/schemas/Jessica' 
        - $ref: '#/components/schemas/Ron'
 examples: 
  "?param=value1": 
    value: 
      id: 10 
      name: Jessica Smith 
  "?param=value2": 
    value: 
      id: 20 
      name: Ron Stewart 
Hrafnkellos commented 6 years ago

Here is an example of how i'm using examples to display multiple error responses from my service Thank you for your example @PavelStefanov ^^

 responses:
      '400':
        description: "Invalid input"
        schema:
          $ref:  '#/definitions/HttpError'
        examples:
          ServiceClosed:
            message: "Today is not a working, service closed"
            error: "ERROR_SERVICE_CLOSED"
            errorCode: 2
          ServiceClosedEvening:
            message: "service closed in the evening"
            error: "ERROR_SERVICE_CLOSED_EVENING"
            errorCode: 3

definitions
  HttpError:
    required:
      - message
    type: object
    properties:
      message:
        type: string
      error:
        type: string
      errorCode:
        format: int64
        type: integer
penja commented 6 years ago

+1

xeroc commented 6 years ago

+1

AlexNik commented 6 years ago

+1

mtrlitza commented 6 years ago

+1

Vetrinus commented 6 years ago

+1

allnulled commented 6 years ago

Hello, people. The same is happening to me today. I just came to give you soulish support

anxolerd commented 6 years ago

Hi. Encountered this issue today.

Is there anything I can help with to get the issue fixed earlier? /cc @PavelStefanov ?

Tamriel commented 6 years ago

Another "workaround" is to use ReDoc instead of swagger-ui.

geodavies commented 5 years ago

Another "workaround" is to use ReDoc instead of swagger-ui.

I agree with Tamriel, this ticket has been open since 23rd Oct 2017 so this obviously isn't a high priority for the swagger guys. This is preventing many of us from being able to use swagger for real projects with real clients.

pascalazenteam commented 5 years ago

@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?

Hello, Not sure this is still valid... but as we met the same issue (2018-12)

In our case it would be sufficient to use the second option in your proposal. Adding a line before and after the ','

A clear display would be to replace the ',' by a logical operator (XOR, OR , AND) but this may require to get separate 'example' display - one for each $ref of the oneOf (XOR) or anyOf (OR) or allOf (AND)

zyv commented 5 years ago

@webron is there anything we can do to help you to get this issue fixed? Is there a BountySource account for swagger-ui / anyone willing to implement this? We would be happy to chip in...

penja commented 5 years ago

âž•