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

Allow multiple examples with optional label #488

Closed
elmolicious opened this issue Oct 20, 2015 · 35 comments
Closed

Allow multiple examples with optional label #488

elmolicious opened this issue Oct 20, 2015 · 35 comments
Labels
example obj/keywords Issues with the Example Object or exampel(s) keywords

Comments

@elmolicious
Copy link

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
Copy link

mkrufky commented Feb 5, 2016

+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
Copy link
Contributor

+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
Copy link
Contributor

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:

  • summary (String) : An optional short description or name
  • description: (String): An optional longer description
  • data (free form object, e.g. what is the current Example Object (I have not found a better name)

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
Copy link

DavidBiesack commented Mar 21, 2017

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
Copy link
Member

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
Copy link
Contributor

arno-di-loreto commented Mar 21, 2017

So we could have something like that:

  • example : Example Object is a freeform object, array or primitive value (or something else as suggested by @DavidBiesack)
  • examples: Array of "Documented Example Object" (naming thing is definitely hard), which is an Object with these properties:
    • summary (String) : An optional short description or name
    • description: (String): An optional longer description
    • value (Example Object): the documented example with a better name thanks to David!

I really like that!

@arno-di-loreto
Copy link
Contributor

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

@DavidBiesack
Copy link

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

@DavidBiesack
Copy link

DavidBiesack commented Mar 21, 2017

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
Copy link
Member

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
Copy link

I say we try to increase the probability of success 😁

@arno-di-loreto
Copy link
Contributor

Can we bribe some people? 😋

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

  • Having something to understand what an example in a list of examples is a must have for human beings.
  • Having something to identify an example (using summary or maybe a new id property) can also help to connect example in parameters/request bodies/responses, this is a must have 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
Copy link

an Examples Object should also allow x- extensions

@ePaul
Copy link
Contributor

ePaul commented Mar 22, 2017

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
Copy link
Member

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
Copy link
Member

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
Copy link
Contributor

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):

  • Example Object (or Example Data):
    • a freeform object, array or primitive value (or something else as suggested by @DavidBiesack)
  • Documented Example Object :
    • summary (String) : An optional short description or name
    • description: (String): An optional longer description
    • value (Example Object): REQUIRED the example value
    • useCaseId (String): A key to connect examples from various sources together (or we use the key of the examples map?)
    • ^x-: this object is extensible
  • Schema Object, Media Type Object, ... anywhere where we can provide example(s):
    • example (Example Object or Documented Example Object or a reference to one of them)
    • examples (Map of Example Object or Documented Example Object or a reference to one of them)
    • we could even get rid of the example property as suggested in Please reconsider duality of .example object and .examples array ? #953 by having a default key like in responses BUT it may make the thing "more complex" for some people who don't use "documented example" feature or for examples for atomic properties.
  • Components Object (where you define reusable object):
    • examples (Map of Example Object or Documented Example Object)

What the proposal achieve

With this proposal:

  • example or examples can be documented (Documented Example Object) or not (Example Object)
  • reusable examples (documented or not) can be defined in the Components Object
  • examples from various source (parameters, request bodies, responses) can be connected by using useCaseId or key in examples Map

Drawbacks:

  • connecting examples is maybe a little bit tricky and over-engineered, it could be easily achieved by using an extension for documentation extremists with the new Documented Example Object which allows extension
  • Does having a Map of two different objects (Example Object and Documented Example Object) may be a problem for tooling?

@ePaul
Copy link
Contributor

ePaul commented Mar 22, 2017

@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
Copy link
Member

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
Copy link
Contributor

fehguy commented Mar 22, 2017

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
Copy link
Member

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
Copy link
Contributor

ePaul commented Mar 23, 2017

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
Copy link
Member

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

@arno-di-loreto
Copy link
Contributor

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:
      - "<Users><User name='Bob'/><User name='Diane'/><User name='Mary'/><User name='Bill'/></Users>"
      - "<Users/>"
  • The examples values are supposed to come from the files which url are located in examples (Request Bodies Object examples). Not OK : How the tools are supposed to make the difference between a String containing a URL pointing to the actual example value and a String contained a URL as an example value?
'application/xml':
    examples:
      - 'http:https://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
Copy link
Contributor

ePaul commented Mar 23, 2017

@MikeRalphson you are right, changed.

@ePaul
Copy link
Contributor

ePaul commented Mar 23, 2017

@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
Copy link
Contributor

arno-di-loreto commented Mar 23, 2017

@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
Copy link
Member

webron commented Mar 24, 2017

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:

  • This feature is not requested by billions of users. A total of 3 is also not a select amount of the community. Silence of others does not mean agreement.
  • @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. As @fehguy mentioned, in this case examples are better than attempted documentation. @arno-di-loreto thanks for your example, but if you look at the details it seems to be incomplete, and does not cover all cases (refs, different types and so on). Yes, writing such examples can be a pain, but at the end of the day, this is exactly what you're asking for others to do with the spec.
  • There's a mistake in the current documentation of the Request Body Object. Those URLs are supposed to be in a Reference Object form and not just as plain text. Nothing should be inferred from it.

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
Copy link
Contributor

ePaul commented Mar 24, 2017

@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
Copy link
Member

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
Copy link

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
Copy link
Contributor

ePaul commented Mar 24, 2017

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
Copy link
Member

@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
Copy link
Contributor

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

  • Parameter Object
  • Media Type Object
  • Header Object
  • Schema Object

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.

  • I totally agree that we must tune the object's structure and work on examples to see if it really works (and I think we're not far from a good solution). Just like with API we will have to live with the choices made here for a long time.
  • I don't agree on the KISS principle which would solve all documentation matters for all reasons stated by @earth2marsh, @DavidBiesack and @ePaul.
  • We also have to deal with so called "poor" designed API (by mistake or by choice to follow some obscure standard which was more relevant than a so called "good" design) and this kind of documentation may greatly ease the "pain"

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

DavidBiesack pushed a commit to DavidBiesack/OpenAPI-specification that referenced this issue Apr 4, 2017
Clarify that Examples Object may be used instead of Example Object.

Show JSON examples as well as YAML

Clarify the $ref values used in examples to remove ambiguity.
These are not references to external JSON/XML/TXT resources, but
rather are references to reusable examples in the current OpenAPI definition
or in an external OpenAPI definition's components/examples

This does not yet address issue OAI#488 but cleans up Examples Object
a bit, which is needed whether we alter the OAS as per OAI#488 .
@handrews handrews added the example obj/keywords Issues with the Example Object or exampel(s) keywords label Jan 29, 2024
@handrews
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
example obj/keywords Issues with the Example Object or exampel(s) keywords
Projects
None yet
Development

No branches or pull requests