Combining defintions in Swagger docs - swagger

I'm documenting an API with Swagger docs. I have several endpoints that share a common set of base properties. I'd like to use $ref to refer to that base set of properties and then extend those properties with additional properties that are unique to each endpoint. I imagined that it would work something like this, but this is invalid:
"properties": {
"$ref": "#/definitions/baseProperties",
unique_thing": {
"type": "string"
},
"another_unique_thing": {
"type": "string"
}
}

Indeed, the example you give here is invalid because $ref can't co-exist with other properties in the same object. $ref is a JSON Reference, and by definition, will cause the other properties to be ignored.
From your question, I assume you're looking for basic composition (rather than inheritance). This is achievable using the allOf keyword.
So, with the example you provided, you would have something like this:
{
"baseProperties": {
"type": "object",
"properties": {
...
}
},
"complexModel": {
"allOf": [
{
"$ref": "#/definitions/baseProperties"
},
{
"type": "object",
"properties": {
"unique_thing": {
"type": "string"
},
"another_unique_thing": {
"type": "string"
}
}
}
]
}
}
YAML version:
definitions:
baseProperties:
type: object
properties:
...
complexModel:
allOf:
- $ref: '#/definitions/baseProperties'
- type: object
properties:
unique_thing:
type: string
another_unique_thing:
type: string
You can also check out the example in the spec.

Related

How do I reference the same schema for both GET and POST requests in OpenAPI 3 if the schema has other references

I have the following OpenAPI 3 schema:
{
...,
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"readOnly": true
},
"name": {
"type": "string"
}
}
},
"Report": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"readOnly": true
},
"user": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
}
Now, if I specify the GET requests for both User and Report everything looks good. The POST request for User is also working. However, the POST request for Report does not work. The body for the Report POST request should look like this:
{
"user": {
"id": 1
}
}
So the "name" property should not be specified since it is only a reference to a user that already exists and will be matched based on the id.
Is it possible to write the Report POST request so it understands that only the id of the user should be specified? Or am I forced to create two different Report schemas, one for the GET request and one for the POST request?
There are a couple ways you can approach this problem. You can either create a definition exclusively for POST, or split your User definition into more atomic components for reuse.
Option 1: Multiple Definitions
Construct your Report user definition to something like this:
"user": {
"id": {
"type": "integer",
"format": "int64",
"readOnly": true
}
}
This has the benefit of being quick and easy, with no impact on other areas of your defnition. But this lends itself to a lot of code duplication, and any future changes to your design will require you to make sure you don't miss any of these special definitions.
Option 2: Split and Reuse Your Definitions
You have a two distinct properties that have different uses, that are used in multiple definitions. This is a good candidate for a ref. Split up your User definition into multiple schemas. Something like this:
"schemas": {
"userId": {
"type": "integer",
"format": "int64",
"readOnly": true
},
"userName": {
"type": "string"
},
"User": {
"type": "object",
"properties": {
"id": {
"$ref": "#/components/schemas/userId"
},
"name": {
"$ref": "#/components/schemas/userName"
}
}
}
This allows you to reuse the userId in your Report with the same definition of what an id actually is. This approach can start getting hard to read as you start growing your definitions into a larger API, but is far more maintainable as your API changes shape over time. Note that this also helps to define the difference between a User ID and a Report ID, which, while sharing the same name, likely hold different data and may have divergent rules over time.

I am having difficulty specifying an XML example for a response in OpenAPI 3

I have a JSON file for OpenAPI 3 that contains the following:
"trait_hasProjectResponse_200": {
"description": "",
"content": {
"application/xml": {
"example": {
"value" : "<project><foo>1</foo><bar>2</bar></project>"
}
}
}
},
This results in the following display on the current swagger-ui:
How do I specify an example of XML for a parameter or response in the OpenAPI 3 spec? I have looked through the documentation and it seems to be targest mostly at JSON. What do I need to do the my output that is generating the OpenAPI 3 JSON file.
I have also tried to use the externalValue and have has similar difficulties.
Remove the value key from the example (value is only used with multiple examples).
"example": "<project><foo>1</foo><bar>2</bar></project>"
Alternatively, you can define a schema for the response, and Swagger UI will generate examples based on the schema. In your example, the schema is a project object that contains the foo array. You can specify [1, 2] as the example values for the foo array:
"components": {
"responses": {
"trait_hasProjectResponse_200": {
"description": "",
"content": {
"application/xml": {
"schema": {
"$ref": "#/components/schemas/project"
}
}
}
}
},
"schemas": {
"project": {
"type": "object",
"properties": {
"foo": {
"type": "array",
"items": {
"type": "integer"
},
"xml": {
"wrapped": false
},
"example": [1, 2]
}
}
}
}
}
This will give you:

How to specify the default XML element text in OpenAPI (Swagger)?

I'm building an OpenAPI (Swagger) 2.0 definition for the following XML payload to use within the Swagger UI:
<addressElement>
<key type="RECORD_ID" item="3">Enter value here</key>
</addressElement>
I'm having an issue figuring out how to display the default value 'Enter value here' for the element key. Where would one place this default value in an OpenAPI definition? My definition looks like this:
"definitions": {
"addressElement": {
"type": "object",
"title": "Address Element",
"properties": {
"key": {
"type": "object",
"properties": {
"type":{
"type": "string",
"example": "RECORD_ID",
"xml":{
"attribute": true
}
},
"item":{
"type": "integer",
"format": "int64",
"example": "3",
"xml":{
"attribute": true
}
}
}
},
},
"xml": {
"name": "addressElement"
}
}
}
This is currently not possible because OpenAPI does not have a way to represent XML elements with attributes such as
<key type="RECORD_ID" item="3">Enter value here</key>
Attributes can only be defined for objects
<obj attr="value">
<elem>Some text</elem>
</obj>
but not for simple <elem>text</elem> elements.
There's an open issue about this limitation here:
How to represent XML elements with attributes
That said, OpenAPI Specification maintainers are considering an option to use alternative data modeling schemas (such as XSD Schema), so your use case might be supported in a future version of OpenAPI.

Can i define nested array objects in swagger 2.0

We are using Swagger 2.0 for our documentation. We are Pro-grammatically creating swagger 2.0 spec straight out our data design documents.
Our Model is very complex and nested. I would like to understand can we define nested array objects defined inline.
for e.g :
{
"definitions": {
"user": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
},
"address": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["home",
"office"]
},
"line1": {
"type": "string"
}
},
"Person": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}
}
}
}
}
We have many cases where we encounter this in our model and defining a #ref is not an option that we want to consider at this time. We need this to handled inline.
As per the following post : https://github.com/swagger-api/swagger-editor/issues/603#evenenter code heret-391465196 looks like its not supported to handle nested array objects defined inline.
Since lot of big enterprise's have a very complex data model we would like to have this this feature to be supported in swagger 2.0 spec.
Is there any thought on this feature to be added.
You document is just invalid and this is not about nested arrays: the property Person is not allowed in a Swagger 2.0 schema inside items.
The only allowed properties in a schema are: $ref, format, title, description, default, multipleOf, maximum, exclusiveMaximum, minimum, exclusiveMinimum, maxLength, minLength, pattern, maxItems, minItems, uniqueItems, maxProperties, minProperties, required, enum, additionalProperties, type, items, allOf, properties, discriminator, readOnly, xml, externalDocs, example.

How to define a map in swagger?

I'm working on an API which also generates swagger documentation. The issue is that for some reasons the request model/schema is not displayed in swagger UI but I don't get any error either.
I need to represent map to an array of strings . e.g. map[string][]string. Definition object definition is below.
{
"definitions": {
"versions": {
"type": "string",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
The support for maps is still not available in the UI - https://github.com/swagger-api/swagger-ui/issues/913.
You'd also want to change your definitions like this:
{
"definitions": {
"versions": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
To be clear, this defines a map where the values are arrays of strings.

Resources