Swagger example attribute hiding all other attributes - swagger

I'm writing a Swagger definition on swaggerhub. There's an option to share models among multiple Swaggers. After swaggers are complete there's an option to download resolved Swagger with the linked definitions imported.
My problem is that this resolved download adds a example node to the models which for whatever reason overrides every attribute when we copy this new Swagger in editor again.
Suppose we have following sample
---
swagger: "2.0"
info:
description: ""
version: 1.0.0
title: title
host: "example.com"
basePath: /
schemes:
- http
consumes:
- application/json
produces:
- application/json
paths:
/test-service:
post:
tags:
- test-service
operationId: test-service
parameters:
- in: body
name: body
description: body
required: true
schema:
$ref: '#/definitions/A'
responses:
201:
description: success
schema:
$ref: '#/definitions/A'
definitions:
A:
type: object
properties:
a1:
type: string
a2:
type: string
Following is how it's displayed in the Swagger UI,
This is correct way, however when I there's an example node in the model A, only example attributes are displayed in the UI,
Here's the change that that I'm referring to
A:
type: object
properties:
a1:
type: string
a2:
type: string
example:
ex1: Hello
ex2: World
Now, if I import this change in the editor, only attributes ex1 and ex2 and actual attributes a1 and a2 are missing.
Problem is exacerbate when we have inheritance.
What happens is whichever lowest node in hierarchy has example attribute only attributes listed in that are shown in the UI, rather than showing all attributes
Here's a sample wi
Now lets introduce example attribute in C. After addition of example attribute at any level all other attributes are ignored.
Here's the link to example attribute documentation https://swagger.io/docs/specification/2-0/adding-examples/.
There's no description of this weird behavior.

That's how example works. Quoting the OpenAPI 2.0 Specification:
A free-form ... example of an instance for this schema.
That is, example is an example for the entire schema. That's why a schema-level example is displayed as is. It overrides any property-level examples, and won't automatically include properties that aren't included in the example.
In your last example with allOf, the schema for A is equivalent to
definitions:
A:
type: object
properties:
a1:
type: string
a2:
type: string
b1:
type: string
b2:
type: string
c1:
type: string
c2:
type: string
example:
ex1: Hello
ex2: world
which again is why the schema-level example from C overrides everything else.
You might want to use property-level examples instead:
definitions:
A:
type: object
properties:
a1:
type: string
example: Hello # <---
a2:
type: string
example: world # <---

Related

Swagger 2.0 duplicated mapping key parser error

I have a swagger file for an API that is going to reside inside IBM API Connect. I typed it out from an IBM tutorial, and I was trying to replicate what the instructor was doing(he did not provide any source files, so I had to type it out).
The tutorial is available here: https://www.youtube.com/watch?v=hCvUYd67rbI
The guy is copy-pasting the swagger file inside the APIConnect local designer around 21:40.
I took the swagger file and put it into http://editor.swagger.io/ and I got a bunch of parser errors:
Errors
Hide
Parser error duplicated mapping key
Jump to line 31
Semantic error at definitions.shipping.properties.xyz.type
Sibling values are not allowed alongside $refs
Jump to line 86
Semantic error at definitions.shipping.properties.cek.type
Sibling values are not allowed alongside $refs
Jump to line 89
I did some digging, and I did not find a lot of resources for my kind of problem. I double-checked if I typed it out correctly from the tutorial. Maybe it has something to do with an older version of API Connect being used in ths tutorial.
Thanks in advance for anyone who can help.
EDIT:
Sorry, it was a bit late so I was tired, I am adding the source code in the yaml file:
info:
x-ibm-name: logistics
title: logistics
version: 1.0.0
schemes:
- https
basePath: /logistics
consumes:
- application/json
produces:
- application/json
securityDefinitions:
clientIdHeader:
type: apiKey
in: header
name: X-IBM-Client-Id
security:
- clientdHeader: []
x-ibm-configuration:
testable: true
enforced: true
cors:
enabled: true
gateway: datapower-gateway
catalogs:
apic-dev:
properties:
runtime-url: $(TARGET_URL)
properties:
shipping_svc_url:
value: 'http://shipping.think.ibm:5000/calculate'
description: Location of the shipping calculator service
encoded: false
paths:
/shipping:
get:
responses:
'200':
description: 200 OK
schema:
$ref: '#/definitions/shipping'
summary: Calculate shipping costs to a destination zip code
operationId: shipping.calc
parameters:
- name: zip
type: string
required: true
in: query
description: Destination zip code.
/stores:
get:
responses:
'200':
description: 200 OK
schema:
$ref: '#/definitions/store_location'
tags:
- stores
summary: Locate store near zip code
operationId: get.stores
parameters:
- name: zip
type: string
required: true
in: query
definitions:
rates:
properties:
next_day:
type: string
example: '20.00'
two_day:
type: string
example: '17.00'
ground:
type: string
example: '8.00'
required:
- two_day
- next_day
- ground
shipping:
properties:
xyz:
type: string
$ref: '#/definitions/rates'
cek:
type: string
$ref: '#/definitions/rates'
required:
- xyz
- cek
store_location:
properties:
google_maps_link:
type: string
example: 'https://www.google.com/maps?q=34.1030032,-118.4104684'
required:
- google_maps_link
There's typo: securityDefinitions defines clientIdHeader, but security refers to clientdHeader (..ntd.. instead of ..enId..).
"Sibling values are not allowed alongside $refs" is not a syntax error, but rather a warning. It's caused by this line:
definitions:
rates:
properties:
...
shipping:
properties:
xyz:
type: string # <---------------
$ref: '#/definitions/rates'
$ref is a JSON Reference, it works by replacing itself and all sibling attributes with the content the $ref is pointing at. So, the type attribute and any other attributes alongside $ref will be ignored. The warning informs you about this in case there are important attributes alongside $ref -- these attributes need to be moved into the $ref'erenced schema to have effect.
That said, xyz being type: string does not make sense, because rates is an object and not a string.
You should also consider adding type: object to the rates, shipping and store_location definitions to indicate that they are objects.

Can a swagger object passed as a parameter have default values in swagger-ui?

I define a path that takes MyObject as a parameter.
MyObject has properties for cats and dogs. These have default values.
In swagger-editor, the example doesn't show the default values, but try-it-out does create a MyObject with correct defaults.
In swagger-ui, I can see the defaults under Models, but not in the API. Is there a way to set these defaults ?
swagger: '2.0'
info:
title: pass object with default properties as a parameter
description: etc
version: "Draft 0.1.1"
host: example.com
basePath: /
produces:
- application/json
paths:
/myobject:
post:
summary: |
post an object.
parameters:
- name: myObject
in: body
required: true
schema:
type: array
items:
$ref: '#/definitions/MyObject'
responses:
200:
description: OK
definitions:
MyObject: # move to/models/model.yml
type: object
description: Contains default properties
required:
- cats
- dogs
properties:
cats:
type: number
default: 9
dogs:
type: string
default: "fido"
Your usage of default is wrong. You probably want example instead.
default is only used with optional fields and is handled on the server side. That is, if the client does not supply a value in the payload, the server will use the default value.
Consider this User model:
definitions:
User:
type: object
required:
- username
properties:
username:
type: string
role:
type: string
enum:
- user
- poweruser
- admin
default: user
The role property is optional and defaults to user. So, if the client sends the payload without role:
{
"username": "bob"
}
the server will assume role=user.
In your case, it looks like you want to provide example values for the fields. This is what the example keyword is for:
definitions:
MyObject:
type: object
description: Contains default properties
required:
- cats
- dogs
properties:
cats:
type: number
example: 9 # <---
dogs:
type: string
example: fido # <---
It seems like there are 2 kinds of defaults:
server-side: variable is not required and server will assume a value for it if it is not given definition from OpenApi v3.0 spec
client side: variable is required and must be only one value (for example headers)
For a client-side default, we can define it by setting required=True and enum to the only allowed value. See this example below:
swagger: "2.0"
info:
title: "some api"
description: "a description"
version: "1.0.0"
host: "example.com"
basePath: "/api"
schemes:
- "http"
paths:
/myobject:
post:
summary: |
post an object.
parameters:
- name: myObject
in: body
required: true
schema:
type: array
items:
$ref: '#/definitions/MyObject'
responses:
200:
description: OK
definitions:
MyObject:
type: object
description: Contains default properties
required:
- cats
- dogs
properties:
cats:
type: number
enum:
- 9
dogs:
type: string
enum:
- fido
And you can see it work in the swagger-editor here: https://editor.swagger.io/
The default parameter is a bit confusing because swagger 2.0 initially described the default parameter without specifying a server or client reference frame.
Swagger 2.0 spec
Defines schema default as
default (Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object)
OpenAPI v3.0 spec
default - The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. For example, if type is string, then default can be "foo" but cannot be 1.

Can a YAML file imported into an API spec reference another include YAML file?

Using swagger-editor and swagger-ui to build a swagger2.0 specification in YAML.
I have split the spec into a client.yml and several model.yml files.
Each model defines some parameters or response objects.
When I open client.yml in the editor, it will load the models into the client using $ref:
However, there appears to be a problem if an object in one of the model files tries to reference an object in another model file.
I have tried absolute and relative paths to no avail. I always get an error, like:
"Reference could not be resolved: /models/basemodel.yml#/BasicObject"
path: Array [10]
error: "Cannot use 'in' operator to search for 'BasicObject' in undefined"
level: 900
type: "Swagger Error"
description: "Reference could not be resolved: /models/basemodel.yml#/BasicObject"
lineNumber: -1
The SimplerObject is identical and works fine. This references a CopyOfBasicObject in the same file. The AdvancedObject tries to reference the BasicObject in a different model file.
The goal is to not copy the definition of BasicObject but refer to it.
It is often necessary to clear the browser cache and reload the page before the editor read the new version of the model file.
The files I used to test this are included. I have converted to a single file as stackoverflow editor is not rendering the yaml very well.
swagger: '2.0'
info:
title: test indirect reference
description: etc
version: "Draft 0.1.1"
host: example.com
basePath: /
produces:
- application/json
paths:
/advancedObjects:
post:
summary: |
post an object.
parameters:
- name: advancedObject
in: body
required: true
schema:
type: array
items:
$ref: '/models/model.yml#/AdvancedObject' # This doeesn't work
#$ref: '/models/model.yml#/SimplerObject' # This works fine
#$ref: '/models/basemodel.yml#/BasicObject' # This works fine
responses:
200:
description: OK
definitions:
AdvancedObject: #move to /models/model.yml
type: object
description: Contains a reference to a basic object
properties:
base:
$ref: '/models/basemodel.yml#/BasicObject'
advanced:
type: array
items:
type: number
CopyOfBasicObject: # move to /models/model.yml
type: object
description: Another simple object
properties:
id:
type: number
SimplerObject: # move to /models/model.yml
type: object
description: Same as AdvanceObject but without reference to another file
properties:
base:
$ref: '#/CopyOfBasicObject'
advanced:
type: array
items:
type: number
BasicObject: # move to /models/basemodel.yml
type: object
description: A simple object
properties:
id:
type: number

Swagger parameter error "is not exactly one from <#/definitions/parameter>"?

I'm trying to write a simple Swagger / Open API definition using the Swagger Editor.
swagger: "2.0"
info:
version: 1.0.0
title: Test API
description: Test API
schemes:
- https
host: hipaa.ai
basePath: /v1
paths:
/comments:
post:
summary: Your comments
description: Comments
parameters:
- name: text
in: body
description: An array of text strings
type: array
minItems: 1
maxItems: 1000
items:
type: text
I'm getting the following error:
Schema error at paths./comments.post.parameters[0]
is not exactly one from <#/definitions/parameter>,<#/definitions/jsonReference>
I've checked the Swagger schema reference, and the petstore example, but I'm not sure why I'm getting this. Any ideas?
Body parameters use the schema keyword to specify the type, so you need to move type, items, minItems and maxItems under schema.
Also, type: text is not a valid type. Use type: string instead.
parameters:
- name: text
in: body
description: An array of text strings
schema:
type: array
minItems: 1
maxItems: 1000
items:
type: string

Swagger 2: use enum reference in query parameter of array type

Can not get how to use reference of string type with enum values in array parameter.
I can make reference in items key and it is working, but Swagger produce error: Not a valid parameter definition
Web UI generates interface, but it have textarea instead of multiselect box I expected.
What is the proper way to do it?
My code:
swagger: '2.0':
paths:
/test:
get:
parameters:
- in: origin
name: status
description: Origin
required: false
schema:
type: array
items:
$ref: '#/definitions/Origin'
collectionFormat: pipes'
definitions:
Origin:
type: string
description: Campaign origin
enum:
- one
- two
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
host: virtserver.swaggerhub.com
basePath: /
Array parameters with items containing $ref are not supported in OpenAPI/Swagger 2.0. But it looks like this will be possible in the next version, 3.0. For now there are a couple of workarounds, see below.
Your spec also has some other issues:
in: origin is not valid. The in keyword specifies the parameter location (path, query, header, etc.) and only accepts certain values as per the OpenAPI/Swagger spec. I guess you meant in: query or in: header.
Typos (or copy-paste errors?): swagger: '2.0': has an extra : at the end and collectionFormat: pipes' has an extra ' at the end.
One solution for having an array parameter containing enum values is to define the enum inline:
parameters:
- in: query
name: status
description: Origin
required: false
type: array
collectionFormat: pipes
items:
type: string
enum:
- one
- two
Another solution (found here) is to use YAML anchors to reference the enum. This is a feature of YAML where you can mark a key with &anchor-name and then further down use *anchor-name to reference that key's value.
definitions:
Origin:
type: string
description: Campaign origin
enum: &origin
- one
- two
paths:
/test:
get:
parameters:
- in: query
name: status
description: Origin
required: false
type: array
collectionFormat: pipes
items:
type: string
enum: *origin
One option is to define a parameter and make a reference to that: (I had an issue with using reference ($ref:) within a query definition)
paths:
/path:
get:
operationId: controllers.controller
parameters:
**- $ref: '#/parameters/SPEC'**
parameters:
SPEC:

Resources