Suppose that I have this definition in a yaml OpenApi definition
definitions:
User:
description: "User"
type: "object"
properties:
firstname:
type: "string"
lastname:
type: "string"
password:
type: "string"
email:
type: "string"
username:
type: "string"
If in a parameters specification I need specific fields of a definition how can I refer them without defining another model as below?
definitions:
UserLogin:
description: "User"
type: "object"
properties:
password:
type: "string"
email:
type: "string"
In your question, you are using definitions keyword what hints that your question is about OpenAPI v2 aka. Swagger. For OpenAPI v3, definitions provided below should be defined inside appropriate Components Object sections.
In order to achieve this, you have to use Composition with keyword allOf. There is a great example that relates to your question here. First, you have to define a smaller object and then include it into the definition of a larger as follows:
definitions:
UserLogin:
description: User Login
type: object
properties:
password:
type: string
email:
type: string
User:
allOf:
- $ref: '#/definitions/UserLogin'
- description: User
type: object
properties:
firstname:
type: string
lastname:
type: string
username:
type: string
It is worth noting that:
Some lighter implementations may not support allOf keyword.
Using composition may increase or decrease the readability of the documentation, depending on the complexity and choice of words used to name the schemas.
Related
I have this OpenAPI schema:
components:
schemas:
User:
type: object
required:
- username
- email
- description
- profile_icon
properties:
username
type: string
email
type: string
format: email
description
type: string
profile_icon
type: string
All of properties are required. This is for PUT /user/profile.
I will change this to PATCH /user/profile.
Users send parameters just they only request to change.
System validates that at least one parameter is required.
How can I describe one of [username, email, description, profile_icon] is required?
Acceptable example requests:
{
"username": "Will Smith"
}
{
"email": "test#example.com",
"profile_icon": "aaaaa.png"
}
Not acceptable example (error):
{}
The anyOf annotator is close but it seems to be only for $ref schemas, not properties.
https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/
The easiest way to require at least 1 property in an object is to use minProperties: 1.
User:
type: object
minProperties: 1 # <--------
properties:
username:
type: string
...
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.
i got this swagger description:
APIExperimentProperties:
type: object
properties:
name:
type: "string"
experimentVariants:
type: array
items:
$ref: "#/definitions/APIExperimentVariantProperties"
owner:
type: "string"
label:
type: "string"
ticketId:
type: "string"
featureName:
type: "string"
APIExperimentVariantProperties:
type: object
required:
- id
- name
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
I wanted to make the fields id and name in APIExperimentVariantProperties to be marked as required in the swagger-ui.
As you can see in the picture, it looks like it worked.
It removed the optional from the field, and their labels are bolder
(the id field vs the featureName field for example).
But I am trying to make their placeholder say that it's required field, just like it did automatically for the field in the image below.
Any idea how to do that? the decimation didn't give any additional leads.
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.
In my API i would like to have a simple model for my collection and a more elaborate model for my individual resource. For example:
a GET request on /libraries should return
BaseLibrary:
type: object
properties:
library_id:
type: string
description: The id of the library
display_name:
type: string
description: Name of the library
href:
type: string
description: The URI linking to this library.
whilst a request to a specific library should return all of the above including an extra parameter books:
So a GET request to libraries/{library_id} should return:
ExtendedLibrary:
type: object
properties:
library_id:
type: string
description: The id of the library
display_name:
type: string
description: Name of the library
href:
type: string
description: The URI linking to this library.
books:
type: array
description: The books in this library
items:
$ref: "#/definitions/books"
I would very much like to not have to define a "BaseLibrary" twice and would want to simple model an additional "ExtendedLibrary" which contains all the responses of a base library and the additional books property.
I tried a lot of different things, with the closest to succes being the following definitions:
definitions:
BaseLibrary:
type: object
properties:
library_id:
type: string
description: The id of the library.
display_name:
type: string
description: Name of the library
href:
type: string
description: The URI linking to this library.
ExtendedLibrary:
type: object
properties:
$ref: "#/definitions/BaseLibrary/properties"
books:
type: array
description: The available books for this library.
items:
$ref: "#/definitions/Book"
However this gives me a "Extra JSON reference properties will be ignored: books" warning and the output seems to ignore this extra property. Is there a clean way to handle my problem? Or am I just going to have to copy paste my whole BaseLibrary model into my ExtendedLibrary model?
As mentioned in the comments section, this may be a duplicate of another question, but it's worth repeating the answer in the context of this particular example. The solution is to use the allOf property in the definition of ExtendedLibrary:
definitions:
Book:
type: object
properties:
title:
type: string
author:
type: string
BaseLibrary:
type: object
properties:
library_id:
type: string
description: The id of the library
display_name:
type: string
description: Name of the library
href:
type: string
description: The URI linking to this library.
ExtendedLibrary:
type: object
allOf:
- $ref: '#/definitions/BaseLibrary'
- properties:
books:
type: array
description: The books in this library
items:
$ref: "#/definitions/Book"
In my experience, Swagger UI visualizes this correctly. When I define an operation response to be ExtendedLibrary Swagger UI shows this example:
{
"library_id": "string",
"display_name": "string",
"href": "string",
"books": [
{
"title": "string",
"author": "string"
}
]
}
Also, Swagger Codegen does the right thing. At least when generating a Java client, it creates an ExtendedLibrary class that correctly extends BaseLibrary.