Swagger / OpenAPI - Diffrent model representations depending on authorization level - swagger

How do i use the Swagger models when i have diffrent representations for each model depending on the authorization level.
For example, a country model for an administrator looks like this:
definitions:
Country:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
example: The Netherlands
code:
type: string
example: NL
created_at:
type: string
example: 2017-06-01 13:37:00
updated_at:
type: string
example: 2017-06-01 14:00:00
However, just a regular user model looks like this
definitions:
Country:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
example: The Netherlands
code:
type: string
example: NL
I was considering to place the model definitions in the response like this:
/admin/countries/{countryId}:
get:
tags:
- AdminCountries
summary: Find a country by ID
operationId: adminCountriesGetById
security:
- Bearer: []
parameters:
- in: path
type: integer
format: int64
name: countryId
required: true
responses:
'200':
description: Success
schema:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
example: The Netherlands
code:
type: string
example: NL
created_at:
type: string
example: 2017-06-01 13:37:00
updated_at:
type: string
example: 2017-06-01 14:00:00
I am not really sure if my "solution" is the correct way to handle this.

The upcoming OpenAPI Specification 3.0 will support oneOf to define multiple possible request/response bodies.
In 2.0, the most you can do is to define the administrator-specific properties as optional and use description to document that these properties are returned for administrators ony and not for regular users.

Related

How to define an OpenAPI ordered array of different objects?

I am trying to define my API using OpenAPI version 3.0. I am trying to generate a YAML file which has four maps, and each map contains a different information. How can I create a YAML file to achieve that goal? I know that my components are not right because of which I am not getting the right result.
Request body should be like this:
[
UserInformation{FirstName, LastName},
AddressInformation{Phone, Address},
ContactInformation{Email, Phone}
]
openapi: 3.0.0
info:
version: 1.0.0
title: 'INPUT-FORM-API'
paths:
/api/v1/test/healthcheck:
get:
summary: Health check for the test api services. Used Internally
operationId: Externalhealthcheck
description: healthcheck for the test services status.
responses:
'200':
description: This status is always returned when service is Ok.
content:
application/json:
schema:
$ref: '#/components/schemas/HealthcheckObject'
/api/v1/test/newformentry:
post:
summary: End Point to insert data into the new table.
operationId: NewFormEntry
description: EndPoint to insert data for new form.
requestBody:
content:
application/json:
schema:
items:
$ref: '#/components/schemas/NewFormEntry'
responses:
'200':
description: This status is always returned when service is Ok.
content:
application/json:
schema:
$ref: '#/components/schemas/HealthcheckObject'
components:
schemas:
NewFormEntry:
$ref: '#/components/schemas/UserInformation'
$ref: '#/components/schemas/AddressInformation'
$ref: '#/components/schemas/ContactInformation'
$ref: '#/components/schemas/MessageFromBene'
UserInformation:
required:
- FirstName
- LastName
properties:
FirstName:
type: string
LastName:
type: string
AddressInformation:
required:
- StreetAddress
- City
- State
- ZipCode
properties:
StreetAddress:
type: string
StreetAddress2:
type: string
City:
type: string
State:
type: string
ZipCode:
type: integer
format: int64
ContactInformation:
required:
- PhoneNumber
- Email
properties:
PhoneNumber:
type: integer
format: int64
maximum: 9
Email:
type: string
HomePhone:
type: integer
format: int64
maximum: 9
Cell:
type: integer
format: int64
maximum: 9
WorkPhone:
type: integer
format: int64
maximum: 9
MessageFromBene:
required:
- Message
properties:
PhoneNumber:
type: integer
format: int64
maximum: 9
Message:
type: string
HealthcheckObject:
required:
- Status
- ErrorMessage
properties:
Status:
type: string
ErrorMessage:
type: string
So the NewFormEntry schema must be an array containing 3 objects, where the 1st object must be UserInformation, the second object must be AddressInformation, and the 3rd object mube be ContactInformation. This is like a tuple, i.e. an ordered sequence of elements where each element has a specfic type. Tuple definitions are slightly different in different OpenAPI versions.
OpenAPI 3.1
If or when you migrate to OAS 3.1, such an array can be defined using prefixItems. This keyword specifies the schema for each element position (in other words, it specifies the order of elements in the array):
components:
schemas:
NewFormEntry:
type: array
prefixItems:
- $ref: '#/components/schemas/UserInformation' # type of the 1st element
- $ref: '#/components/schemas/AddressInformation' # type of the 2nd element
- $ref: '#/components/schemas/ContactInformation' # type of the 3rd element
minItems: 3
maxItems: 3
additionalItems: false # can be omitted if `maxItems: 3` is specified
OpenAPI 3.0
In OAS 3.0, you can define the array length (i.e. 3 items) and the possible types of array items (i.e. each item can be either A, B, or C), but there's no way to define a specific order of objects in the array. So the most you can do is this:
components:
schemas:
NewFormEntry:
type: array
items:
oneOf:
- $ref: '#/components/schemas/UserInformation'
- $ref: '#/components/schemas/AddressInformation'
- $ref: '#/components/schemas/ContactInformation'
minItems: 3
maxItems: 3
Note that this definition allows arbitrary order of objects in the array and also multiple instances of the same object (e.g. [UserInformation, UserInformation, UserInformation]). You might want to implement additional backend validations to verify the desired order of objects in this array.

Can OpenAPI integrate HATEOAS in a useful way?

Is it possible to describe a HATEOAS REST API with OpenAPI?
When I describe the API in HAL Format I would need to define three schemas for it (one for Request Payloads, one for Collection Resource and one for Item Resource). For Example:
components:
schemas:
Link:
type: object
properties:
href:
type: string
hreflang:
type: string
title:
type: string
type:
type: string
deprecation:
type: string
profile:
type: string
name:
type: string
templated:
type: boolean
Links:
type: object
discriminator:
propertyName: _links
properties:
_links:
type: object
additionalProperties:
type: string
$ref: "#/components/schemas/Link"
CollectionModel:
type: object
discriminator:
propertyName: _embedded
properties:
_embedded:
type: object
_links:
type: object
properties:
self:
type: string
profile:
type: string
search:
type: string
CollectionModel_Foo:
type: object
allOf:
- $ref: "#/components/schemas/CollectionModel"
properties:
_embedded:
type: object
properties:
projects:
type: array
items:
$ref: "#/components/schemas/EntityModel_Foo"
EntityModel_Foo:
type: object
allOf:
- $ref: "#/components/schemas/Foo"
- $ref: "#/components/schemas/Links"
Foo:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
bar:
type: string
I don't find that very useful because that complicates the specification and since when generating a client based on that schema using OpenAPI Generator the client does not pay attention to HATEOAS and simply requests the resources. So in this context it is useless.
I thought about implementing JSON:API but sadly the full JSON Schema is only supported in the current OpenAPI 3.1 draft.
All in all I can't find a proper way to integrate OpenAPI in a HATEOAS API.

Swagger UI displaying array example as null

I use OpenAPI 3.0.0 and want to pass an array of Items as a parameter in the requestBody. My API definition looks like this:
post:
tags:
- test
summary: Test dummy
operationId: requestBodyTests
requestBody:
description: test the body
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Items'
components:
schemas:
Items:
type: array
items:
$ref: '#/components/schemas/Item'
examples:
- id: bla
text: blubb
- id: bla
text: blubb
Item:
type: object
properties:
id:
type: string
name:
type: string
Swagger UI displays the request body example as follows:
and the request body schema as follows:
Why does it show an orderedmap instead of my normal objects?
Can someone tell me how to do the spec right for having the array with items correct?
Examples inside schemas use the example keyword (singular), not examples (plural).
Also, your YAML indentation is wrong - Items and Item must be indented under schemas, list items in the example must have the same indent, etc. If you paste your spec into http://editor.swagger.io, it will point out syntax errors.
Here's the fixed version:
components:
schemas:
Items:
type: array
items:
$ref: '#/components/schemas/Item'
example: # <------
- id: bla
text: blubb
- id: bla
text: blubb
Item:
type: object
properties:
id:
type: string
name:
type: string
Moreover, you get an example as 'orderedmap' because the example field is A free-form property.
But represent examples that cannot be naturally represented in JSON or YAML, a string value can be used to contain the example with escaping where necessary. (OpenAPI spec)
We can write an example as 'string' in both ways:
1.
example: '[ currency: USD, amount: 123 ]'
example: |
[
currency: USD,
amount: 123
]

Swagger: how to represent a property whose type is oneOf a list of types?

I have an object that has a property that is an object whose type would be one of list of types. All my attempts have been rejected by Swagger Editor with the following error:
Data does not match any schemas from 'anyOf'
Jump to line 43
Details
Object
code: "ANY_OF_MISSING"
message: "Data does not match any schemas from 'anyOf'"
path: Array [7]
inner: Array [2]
level: 900
type: "Swagger Error"
description: "Data does not match any schemas from 'anyOf'"
lineNumber: 43
The full swagger specification file is as follows (the field in question is DataSetsInquiryRsp.dataSets.dataSet):
swagger: '2.0'
info:
title: My API
description: My Awesome API
version: 1.0.0
paths:
/dataSetsInquiry:
get:
description: Retrieve one or more data-sets.
parameters:
- name: ids
in: query
description: List of identifiers of requested data-sets.
required: true
type: array
items:
type: string
responses:
'200':
description: Requested data-sets.
schema:
$ref: '#/definitions/DataSetsInquiryRsp'
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
definitions:
DataSetsInquiryRsp:
type: object
additionalProperties: false
properties:
sessionIdentifier:
description: Identifier of the secure session with the server.
type: number
dataSets:
type: object
additionalProperties: false
properties:
id:
type: string
dataSet:
type: array
items:
oneOf:
- $ref: '#/definitions/Customer'
- $ref: '#/definitions/Merchant'
Customer:
type: object
additionalProperties: false
properties:
firstName:
description: First name of the customer
type: string
lastName:
description: Last name of the customer
type: string
Merchant:
type: object
additionalProperties: false
properties:
code:
description: Code the Merchant.
type: string
name:
description: Name of the Merchant.
type: string
Well, the issue is simply the fact that Swagger doesn't support oneOff. In fact, Swagger supports a subset of Json-Schema and add a few things (datatype file for instance).
What is bad here is the error returned by Swagger. It doesn't help match. And this is the case of all Json-Schema validators I have worked with so far: is-my-json-valid, jsen.

How to reference top-level parameters in Swagger 2.0

I'm trying to figure out how to use top level parameters and then, at the operation level,use a $ref to refer to the definition that was declared at the top level object.
Here is what the YAML looks like but when I try this I get an empty parameter displayed. Anyone know the correct syntax for this?
swagger: '2.0'
info:
version: 0.1.0
title: Customer API
parameters:
index:
name: index
in: query
description: Specifies the offset of the first item to be returned. The default value is 0, which starts at the beginning.
type: integer
default: 0
minimum: 0
paths:
/customers:
get:
parameters:
- $ref: '#/parameters/index'
responses:
200:
description: List all customers
schema:
$ref: '#/definitions/Customers'
definitions:
Customer:
properties:
name:
type: string
id:
type: integer
format: int32
Customers:
properties:
startIndex:
type: integer
itemsPerPage:
type: integer
totalResults:
type: integer
entries:
type: array
$ref: Customer
The support for this has yet to be implemented in swagger-ui. See https://github.com/swagger-api/swagger-ui/issues/621.

Resources