Multiple Response Body Examples depending on media type in OpenApi 3.0.0/Swagger - api

I am trying to document the response for an endpoint that accepts multiple mime type requests and returns a different response based on the type. One response type, pdf, returns its own schema separate from the others. The rest all return the same schema and same example. This syntax works. Almost. Except in the UI example, the JSON response is also showing the string "$ref: example-two.json" along with the appropriate response example. Like:
{
"key": "value",
"key2": "value2",
"$$ref: example-two.json"
}
when it should just be:
{
"key": "value",
"key2": "value2"
}
I've been scouring the docs and stack and google and I don't see any examples of making something like this work. Or rather, I'm not seeing why this one isn't working, but I haven't seen any examples that include $refs for each example.
responses:
200:
content:
application/pdf:
schema:
$ref: ../app.yaml#/components/schemas/ModelOne
application/json:
schema:
$ref: ../app.yaml#/components/schemas/ModelTwo
examples:
Example:
value:
$ref: example-two.json
text/html:
schema:
$ref: ../app.yaml#/components/schemas/ModelTwo
examples:
Example:
value:
$ref: example-two.json
For context - I cannot change the endpoint behavior and I do need to show an example for each mime type even if they are the same. Because the one is different. Thank you in advance!

There are two ways to $ref an example in OpenAPI 3.0:
1) Define the example in the components/examples section. In this case the $ref is used inside the examples.<name> key (not inside value).
examples:
Example:
$ref: '#/components/examples/MyExample'
...
components:
examples:
MyExample:
summary: Optional short description of this example
value:
key: value
key2: value2
2) If the example-two.json file contains just the example value (in this case - sample JSON), you can use externalValue to link to that file:
examples:
Example:
externalValue: example-two.json
Notes:
Relative URLs in externalValue are resolved against the API server URL (servers[*].url) and not the location of the OpenAPI definition file. You may need to use an absolute URL.
Examples with externalValue are currently (as of December 2019) not displayed in Swagger UI - see issue #5433.

Related

Can I compose two JSON Schemas in a third one?

I want to describe the JSON my API will return using JSON Schema, referencing the schemas in my OpenAPI configuration file.
I will need to have a different schema for each API method. Let’s say I support GET /people and GET /people/{id}. I know how to define the schema of a "person" once and reference it in both /people and /people/{id} using $ref.
[EDIT: See a (hopefully) clearer example at the end of the post]
What I don’t get is how to define and reuse the structure of my response, that is:
{
"success": true,
"result" : [results]
}
or
{
"success": false,
"message": [string]
}
Using anyOf (both for the success/error format check, and for the results, referencing various schemas (people-multi.json, people-single.json), I can define a "root schema" api-response.json, and I can check the general validity of the JSON response, but it doesn’t allow me to check that the /people call returns an array of people and not a single person, for instance.
How can I define an api-method-people.json that would include the general structure of the response (from an external schema of course, to keep it DRY) and inject another schema in result?
EDIT: A more concrete example (hopefully presented in a clearer way)
I have two JSON schemas describing the response format of my two API methods: method-1.json and method-2.json.
I could define them like this (not a schema here, I’m too lazy):
method-1.json :
{
success: (boolean),
result: { id: (integer), name: (string) }
}
method-2.json :
{
success: (boolean),
result: [ (integer), (integer), ... ]
}
But I don’t want to repeat the structure (first level of the JSON), so I want to extract it in a response-base.json that would be somehow (?) referenced in both method-1.json and method-2.json, instead of defining the success and result properties for every method.
In short, I guess I want some kind of composition or inheritance, as opposed to inclusion (permitted by $ref).
So JSON Schema doesn’t allow this kind of composition, at least in a simple way or before draft 2019-09 (thanks #Relequestual!).
However, I managed to make it work in my case. I first separated the two main cases ("result" vs. "error") in two base schemas api-result.json and api-error.json. (If I want to return an error, I just point to the api-error.json schema.)
In the case of a proper API result, I define a schema for a given operation using allOf and $ref to extend the base result schema, and then redefine the result property:
{
"$schema: "…",
"$id": "…/api-result-get-people.json",
"allOf": [{ "$ref": "api-result.json" }],
"properties": {
"result": {
…
}
}
}
(Edit: I was previously using just $ref at the top level, but it doesn’t seem to work)
This way I can point to this api-result-get-people.json, and check the general structure (success key with a value of true, and a required result key) as well as the specific form of the result for this "get people" API method.

How to define UUID property in JSON Schema and Open API (OAS)

When using JSON Schema and Open API specification (OAS) to document a REST API, how do I define the UUID property?
There's no built-in type for UUID, but the OpenAPI Specification suggests using
type: string
format: uuid
From the Data Types section (emphasis mine):
Primitives have an optional modifier property: format. OAS uses several known formats to define in fine detail the data type being used. However, to support documentation needs, the format property is an open string-valued property, and can have any value. Formats such as "email", "uuid", and so on, MAY be used even though undefined by this specification.
For example, Swagger Codegen maps format: uuid to System.Guid in C# or java.util.UUID in Java. Tools that don't support format: uuid will handle it as just type: string.
The only way I found so far is to manually specify the RegEx pattern as reusable schema component:
openapi: 3.0.1
paths:
/transactions/:
post:
responses:
200:
content:
application/json:
schema:
type: object
properties:
transactionId:
$ref: '#/components/schemas/uuid'
components:
schemas:
uuid:
type: string
pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
# the regex above limits the length;
# however, some tools might require explicit settings:
minLength: 36
maxLength: 36
But, I would definitely want to use a more standardized approach.
Since the question was originally asked the JSON Schema spec has been extended to provide built-in support for specifying and validating that a JSON field of type string is a UUID - specifically that it adheres to the format of a UUID as defined by RFC4122, e.g. “f81d4fae-7dec-11d0-a765-00a0c91e6bf6”.
The support was added in JSON Schema spec version 2019-09 (previously known as draft-08). The JSON Schema Validation component spec was extended such that the existing ‘format' keyword that can be specified for schema fields of type string now supports a new built-in format named "uuid".
The example JSON schema below declares a (mandatory) field named "id" of type string that must be formatted as UUID -
{
"$schema": "http://json-schema.org/draft/2019-09/schema#",
"title": "My JSON object schema",
"description": "Schema for the JSON representation of my JSON object.",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for my object. (A UUID specified by RFC4122).",
"type": "string",
"format": "uuid"
}
},
"required": ["id"]
}
Note that at the time of writing, the section of the JSON Schema user guide ("Understanding JSON Schema") covering examples of built-in string validation - JSON Schema Reference > Type-specific keywords > string > Format - doesn’t mention UUID supports, as it’s out of date - it currently only describes JSON Schema draft-7.
For the Java developers among you, the RFC4122 format used by JSON schema is compatible with the string representation of Java’s UUID class - it’s Javadoc also mentions RFC 4122.
For more details see -
The JSON Schema Validator spec section 7. A Vocabulary for Semantic Content With “format” > 7.3. Defined Formats > 7.3.5. Resource Identifiers - The official spec.
This GitHub issue https://github.com/json-schema-org/json-schema-spec/issues/542 (01/2018) requested that support be added. And the enhancement was duly implemented in 03/2019. See pull request https://github.com/json-schema-org/json-schema-spec/pull/715.

Is the way to exclude property from body type (RAML)?

Is there a way to exclude one or more properties from a request body when you use a type and writing your API using RAML 1.0
I'll explain. I have a type: 'Order' with a set of properties. I have a resource /orders and a method post which allows users to create a new order.
The request body is an order struct json and a response is an order struct as well.
But I don't want users to specify order id while they are submitting their request. But that id (and a couple more 'response only' fields) will be returned at the response. I don't want to create an extra type, like OrderRequest and then inherit it with an Order type, maybe there is a more elegant solution?
So I want to have a way to exclude some properties from a request body and keep others in order to use their description and examples.
Thanks and sorry for my English :)
Use two types. The second will be child of the first. Example:
#%RAML 1.0
title: GitHub API
version: v3
baseUri: https://api.github.com
mediaType: application/json
types:
OrderCreating:
type: object
properties:
products:
description: List of product ids with amount.
required: true
type: object
properties:
[]:
type: number
coupon?: string
Order:
type: OrderCreating
properties:
id: integer
price: number
...
/orders:
post:
body:
application/json:
type: OrderCreating
/{orderId}:
get:
responses:
200:
body:
application/json:
type: Order
Also you can include Library with declaration of your types.
As you don't want to create an extra type with inheritance you can still mark the field as optional and document that it is present in the response.

extending a resource endpoint with extra data?

Is it generally a bad idea to optionally extend a resource endpoint with additional data pertaining to the requested resource?
Example
GET /post/:id/ - retrieve a single post
Example Response
{
id : 1
title : 'Hello world',
body : 'Testing'
}
GET /post/:id/?includeMeta=1 - retrive a single post with additional meta data
Example Response
{
id : 1
title : 'Hello world',
body : 'Testing',
meta : {
url : 'http://google.com',
customMetaKey : 'some value'
}
}
It depends on whether these extra values belong to the main resource or not. In your case, if they belong to the resource named "Post" then it's perfectly acceptable. In fact, you can use an approach named "Partial Responses", that was first used by Google. In this case, you have to add a special QueryString attribute named "fields" like the example below.
GET /post/:id/?fields=metadata,field2,field3,association(field1,field2)
In this queryString you can add all fields you want returned in the response, including the associations. Take a look at the article below to learn more about Partial Responses:
http://googlecode.blogspot.com.br/2010/03/making-apis-faster-introducing-partial.html
In the other hand, if these extra values don't belong to the main resource then I think it doesn't make any sense. If a client wants those values then it has to ask it to the resource that owns it.

Describing URI parameters in RAML

I'm declaring a REST service API stub in RAML. My web application provides equipment, which can be listed, obtained by id or by code. When I want the whole list, I don't specify any URI parameter, however, to get a concrete equipment, I do. That's its current state:
/equipment:
get:
body:
application/json:
application/xml:
description:
List all the equipment
/id/{equipmentId}:
get:
body:
application/json:
application/xml:
description:
Get an equipment by id
/code/{code}:
get:
body:
application/json:
application/xml:
description:
Get an equipment by code
Here, in description fields I write what the current call performs. However, I would like to add a description for the parameter passed in the URI itself (id or code). Is there a way to achieve it?
You are missing uriParameters sections to describe the equipmentId and code parameters. In such section, you can specify the usual: type, description...
See section Template URIs and URI Parameters in the spec: https://github.com/raml-org/raml-spec/blob/master/versions/raml-08/raml-08.md#template-uris-and-uri-parameters