OAI / OpenAPI-Specification

The OpenAPI Specification Repository
https://openapis.org
Apache License 2.0
28.97k stars 9.07k forks source link

Allow multiple examples with optional label #488

Closed elmolicious closed 5 months ago

elmolicious commented 9 years ago

Hi, for some routes we need multiple examples for a "Response Object" as well as multiple body payload examples in the "Parameter Object".

e.g: our API route returns an object with optional properties and we want to show 2 examples how it could look like ...

...
{
    ...
    "examples" : [
        {
            "application/json" :
                {
                    "property" : "value"
                }
        },
        {
            "application/json" :
                {
                     "property" : "value",
                     "optional_property" : "value"
                }
        }
    ]
    ...
}

In addition we would like to name/label these examples . In the specification "Example Object"s you can specify different representations of an example for a given MIME-type. I would suggest adding either an optional "name" or "label" property to the "Example Object" which is a string (maybe even an object to allow localized string values for different languages) or to allow custom properties (e.g x-name).

e.g:

...
{
    ...
    "examples" : [
        {
            "application/json" :
              {
                    "property" : "value"
              },
            "name" : "Default Response"
        },
        {
            "application/json" :
                {
                     "property" : "value",
                     "optional_property" : "value"
                },
            "name" : "Response if state of ressource ..."
        }
    ]
    ...
}

If there is any good way to solve it with the current swagger specification, i would love to hear it and it would make this feature request obsolete.

Thanks.

mkrufky commented 8 years ago

+1 I also have an endpoint that can be used in different ways. The required and optional argument fields can vary depending on the function being carried out. It would be great to be able to represent the same endpoint multiple times, specifying different arguments (and response body), rather than having to represent it all at once, marking all arguments as optional

arno-di-loreto commented 8 years ago

+1 having a description in addition to the name would be great too All this could like like this maybe:

examples:
  - name: An first example
    description: use case
    content:
      - application/json : <example for media type application/json>
      - application/xml: <example for media type application/xml>

That could be useful for documentation but I think also for mock API generation

arno-di-loreto commented 7 years ago

Based on how Example Object are defined and used in version 3.0.0-rc0, I think that the it could be slightly modified to provide documentation data this way:

Current Example Object is a freeform object, array or primitive value.

Modified Example Object is an Object with these properties:

Having documented examples, or at least named examples is definitely a must have when documenting an API, especially if you provide various examples: how the readers would know what is the difference between these examples.

@webron or @darrelmiller what do you think about this?

DavidBiesack commented 7 years ago

1+, but rather than "just free form object", we should not imply that a JSON object is required; an Example could be a array or even a primitive value. (I htink Example Object is currently named incorrectly since it is not always an Object, but if we adopt your suggestion, the name would be correct.)

I suggest value instead of data.

darrelmiller commented 7 years ago

I wonder if we can kill two birds with one stone here. There has been a question about the redundancy of having example and examples #953. Perhaps we can leave example as the freeform simple scenario with no metadata and have the examples be an array of objects as @arno-di-loreto has described them. The need for a description only really arises when there are multiple examples. I also like the idea of having summary and description properties.

arno-di-loreto commented 7 years ago

So we could have something like that:

I really like that!

arno-di-loreto commented 7 years ago

I'm wondering if the summary property shouldn't be required?

DavidBiesack commented 7 years ago

summary is not required in other places, even where it is a "good idea". I don't think it should be required here.

DavidBiesack commented 7 years ago

If we keep example, let's not call it Example Object, just Example or Example Value; and for the array use [ Example Object ]; .value is an Example (or Example Value)

darrelmiller commented 7 years ago

Although I am a fan of this idea, be warned that getting any new features into the spec at this point does not have a high probability of success.

DavidBiesack commented 7 years ago

I say we try to increase the probability of success :grin:

arno-di-loreto commented 7 years ago

Can we bribe some people? πŸ˜‹

In current state the examples property may not be usable IMHO especially for documentation, mocking and testing tooling.

And postponing this modification that billions of people will ask for will lead to a breaking change later 😁

DavidBiesack commented 7 years ago

an Examples Object should also allow x- extensions

ePaul commented 7 years ago

Looks like everyone here thinks this is a good idea (though the only one from the @OAI/tdc who said something was @darrelmiller, so it might not be representative for the decision makers) ... who wants to write it up into a pull request?

darrelmiller commented 7 years ago

Just one other item that was just brought to my attention. With examples as an array and summary/description as optional fields it becomes possible to define multiple examples with no way of identifying or referencing one example vs another. That could make life difficult for tooling. We have a couple of options. We could introduce a name property as was suggested earlier by @arno-di-loreto or the array could be a map and the key becomes the identifier.

darrelmiller commented 7 years ago

And @fehguy and @webron have been busy showing off their new Swagger at Interconnect, so their lack of commentary should not be construed as a lack of opinion :-)

arno-di-loreto commented 7 years ago

I've just realized that the proposed structures (see my comment) is not really usable with components.examples which is a map of reusable Example Object. We need to update it.

Proposal

So, I propose this modification (including what @darrelmiller propose for identifying/naming examples):

What the proposal achieve

With this proposal:

Drawbacks:

ePaul commented 7 years ago

@arno-di-loreto Having either a documented example object or a "simple example object" in the same place gives the problem that you can't decide which one you have – a simple example object, as a free form object, could look just the same as a documented example. (E.g. suppose you want to give an example for the documented example object.)

earth2marsh commented 7 years ago

I agree that having a name and description (and sure, summary!) are important for explaining why each example exists, otherwise, as @arno-di-loreto points out, how will people know? This has come up in my experience with finance APIs, where a transaction might benefit from examples of each of check, credit, cash, or transfer. Without some way to explain why each example matters, it becomes example soup.

I agree with @DavidBiesack that x- should be considered, though it could be unclear whether it is part of the example itself. I wonder if I could argue that an example value might be better if it were always a string rather than an object (e.g. if the object had x- is it part of the object or describing the object?). I do also worry how adding examples can blow out the size of a spec, but that's not a great reason not to do it.

…and not least of the issues is @darrelmiller 's point that changes are trickier at this stage.

fehguy commented 7 years ago

Share an example yaml of your proposal @arno-di-loreto. My concern is that we're adding a zillion levels of objects here, and while some fields are nice to have, they will become a burden for 99% of the use cases.

darrelmiller commented 7 years ago

My suggestion would be that reusable examples in #/components/examples would only be the "documented examples". I don't like the idea of tooling having to figure out which it is.

So, here's my suggestion. example stays the same as it is in V2 and examples would end up working similar to the way links work.

response:
  200:
     description: My cat
     content:
       application/json:
         examples:
           minimal:
              summary: A minimal cat representation
              value:  
                name: Fluffy
                colour: Brown
           complete:
                ref$ : "#/components/examples/complete-cat-response"
         application/xml:
           example: "<cat @name='Fluffy' @colour='Brown'></cat>" 
ePaul commented 7 years ago

For the cases where the example is at some external URL (like in the Request body examples in RC0) I would use a url property or similar, instead of trying to derive this fact from the content.

(This would be especially useful for media types which are not representable as a simple string, like an image.)

So the documented example object would have these fields:

Field name Type description
summary String a short description or name
description String a longer description
value Any the full example, as a JSON/YAML value (if the media type is a JSON or YAML one) or a String (if the media type is anything else). Cannot be used together with url.
url String a URL to a complete example document. Cannot be used together with value.

It is required to use one of value or url.

(Edited to use url instead of href.)

MikeRalphson commented 7 years ago

@ePaul just colouring the bikeshed a little by saying that URL properties are called url elsewhere in the spec, not href.

arno-di-loreto commented 7 years ago

I'm a bit puzzled by how examples is presented in the spec and I think that what we propose can clarify this.

'application/xml':
    examples:
      - 'http://foo.bar/examples/user-example.xml'

The Example Object description do not mention this.

@ePaul I like the idea of adding a url to Documented Example Object (at first I thought this URL pointed to external documentation :-) ) and having the value as an Any object.

But what about the example object? Do we keep it as it is?

ePaul commented 7 years ago

@MikeRalphson you are right, changed.

ePaul commented 7 years ago

@arno-di-loreto Yes, this is the reason I proposed the url field.

I would define the Examples object (in a media type object) as [ Documented Example Object | Reference Object ], with the reference referring to a Documented Example Object in components/examples.

I think we should get rid of the Example Object ... it is not even always an object.

We could let the singular example property be a shortcut to examples with a single documented example, i.e.

example: X

would be synonym to this:

examples:
   - value: X

Having a reference here would be out, because it can't be distinguished from an example value which just happens to look like a reference – or which is an example for a reference object.

arno-di-loreto commented 7 years ago

@fehguy Here's an example of documented example and also the "linking examples thing" based on key

https://gist.github.com/arno-di-loreto/a2cec5af36bd34e8921a7c88e2c95adb

I think that a map would be better for linking examples together (or we'll need to add a property or use summary). But, I would understand that some people found this feature a little over-engineered :-)

webron commented 7 years ago

Well, that was a thrilling read. Interesting to see people are so engaged by something like examples. Apologies for the lengthy reply (though you should be used to it by now).

The good news - unlike my colleagues, I'm not particularly opposed to making such changes at this stage, especially if they are meant to address a burning concern.

The bad news - I'm not convinced this is the case.

It's going to be difficult to address everything that was raised, so I might miss a few things:

Now for the big thing. Congratulations, you have managed to take something simple and make it into a beast. It doesn't feel over-engineered, it is over-engineered. I'd argue that the examples in @arno-di-loreto's example should come as part of the description and that's it. For documentation purposes, it's good enough. I get the case the mocking, but I'm not convinced this is one of the goals of the spec. I'd even take it one step further and say (and not to offend anyone), that if your API is built in such a way that it's so complicated that you have to provide multiple examples to fully explain how that operation works - maybe you'd want to reconsider your API design and simplify things. KISS does apply to API design as well. I am 100% sure that there are use cases out there where there is no choice in the matter, but we might end up enabling these design choices by adding this feature.

This feature will make the specs bloated. It will make them a pain to navigate, a pain to read, and definitely a pain to write. It can easily double and triple the size of a simple spec. It's starting to feel that if this is such an important feature, it might be smarter to have a supporting document, simply linking operationId's to examples (yes, including responses and such) - but that's a whole other adventure.

However, as much as I don't think it's a good idea, I'm likely not to oppose to it if you can come with a relatively clean solution. Of course I'm just one voice in the team, but that's my take. The solution doesn't necessarily have to cover everything you want. Please avoid writing up the actual documentation of the changes, but really provide a set of examples that cover different use cases. This is how we dealt with a lot of the features that made it into the spec. I also ask that you avoid dealing with naming right now (it really isn't important if something is an Object or not, if you use href or url) - focus on the functionality first.

ePaul commented 7 years ago

@webron Thanks for your feedback.

I'd even take it one step further and say (and not to offend anyone), that if your API is built in such a way that it's so complicated that you have to provide multiple examples to fully explain how that operation works - maybe you'd want to reconsider your API design and simplify things.

With the new support of JSON schema's anyOf and oneOf I would say you'll need more than one example more often than with OpenAPI 2.0.

@arno-di-loreto and @ePaul are proposing different structures. To be honest, I'm not sure anymore which structure is the one we're expected to decide on.

I guess the point is that the fleshing-out of the features is not yet finished here. I'll try to come up with some use cases.

darrelmiller commented 7 years ago

The fact that the OpenAPI spec uses multiple examples to describe many of the features suggests there is value to providing multiple examples. Not being able to explain to describe each of those examples is a significant shortcoming.

One of the primary roles of OpenAPI is to drive documentation. Saying that API documentation can only include one example per request/response body is going to drive people some people to externalize documentation in an ad-hoc way, and cause others to produce less than ideal documentation due to these constraints. I don't think either outcome is in the best interest of OpenAPI.

I'm not convinced that adding a identifier and a description to an example is over-engineering.

DavidBiesack commented 7 years ago

Addressing @earth2marsh 's earlier comment: x- is not in conflict because like description, x- values would be siblings of value in an Example Object

I agree with @ePaul; this is especially true for APIs which use just application/json their Media Type objects will be complex and can't split out multiple request/response representations by media types.

Good documentation (which includes good examples - emphasis on plural) is key to successful adoption of APIs. This does not mean the API is designed poorly, it just means it is documented well. Restricting metadata on examples will not lead to better API design. There are plenty of request or response bodies which have mutually-exclusive variation/representation -- most notably, when a discriminator is in play.

I don't consider an object of four fields to be a "beast". The real issue is: if we do not do this now, we can never do this - we're shutting a door to future extension that I believe we will regret.

ePaul commented 7 years ago

Just to add to the confusion: Is this whole proposal we are working on about the example(s) in the media type object, the example(s) in the schema objects, or both?

darrelmiller commented 7 years ago

@ePaul Both. I'm going to try and write up a PR with the proposed changes and then we will beat it into something we can all live with.

arno-di-loreto commented 7 years ago

@ePaul : To be consistent, I think that this proposal MUST apply to all examples:

And we also must not forget to impact the examples property in Components Object (where you define reusable examples).

@webron Thank you for your feedback.

@darrelmiller Do you need help or have you everything you need for the PR?

PS: That proposal MAY be a way to solve #348 (documenting enums)

handrews commented 5 months ago

There was a PR merged for this in 2017 and no further comments. Closing.