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.
Related
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
I'm using http://editor.swagger.io to design an API and I get an error which I don't know how to address:
Schema error at paths['/employees/{employeeId}/roles'].get.parameters[0]
should NOT have additional properties
additionalProperty: type, format, name, in, description
Jump to line 24
I have other endpoints defined in a similar way, and don't get this error. I wondered if I had some issue with indentation or unclosed quotes, but that doesn't seem to be the case. Google also did not seem to provide any useful results.
swagger: "2.0"
info:
description: Initial draft of the API specification
version: '1.0'
title: App 4.0 API
host: api.com
basePath: /v1
tags:
- name: employees
description: Employee management
schemes:
- https
paths:
/employees/{employeeId}/roles:
get:
tags:
- employees
summary: "Get a specific employee's roles"
description: ''
operationId: findEmployeeRoles
produces:
- application/json
parameters:
- name: employeeId <====== Line 24
in: path
description: Id of employee whose roles we are fetching
type: integer
format: int64
responses:
'200':
description: successful operation
schema:
type: array
items:
$ref: '#/definitions/Role'
'403':
description: No permission to see employee roles
'404':
description: EmployeeId not found
Any Hints?
The error message is misleading. The actual error is that your path parameter is missing required: true. Path parameters are always required, so remember to add required: true to them.
Had the same problem. I accidentally mixed up the syntax from Swagger 2.0 with Openapi 3.0.x. In Openapi 3.0.x, definitions are redefined as components. In the online editor you can click on the button Edit > Convert to OpenAPI 3 to use Openapi 3.0.x.
Read more about components here.
Remark:
OAS 3 is the latest version of the
OpenAPI Specification.
For me the cause of the error was a missing a leading slash in the path (internal/resource instead of /internal/resource).
And yes the error message is extremely unhelpful.
In my case I was missing parameter definition in api definition
- name: parameterName
in: query
description: parameter's description here.
required: false
schema:
type: string
In my case it had the wrong indentation for the example. It was:
content:
application/json:
schema:
$ref: '#/components/schemas/someresponse'
examples:
example1:
value:
param1: "some string"
param2: "123"
Rather than:
content:
application/json:
schema:
$ref: '#/components/schemas/someresponse'
examples:
example1:
value:
param1: "some string"
param2: "123"
But the VScode open api preview with swaggerUI didn't show any errors and everything looked valid.
The syntax requires might require two parameters, as mentioned by Helen required: true is need so is type:DataType . The error is misleading.
I'm new to Swagger. I've written the following code using Swagger Editor, but I'm getting multiple errors. I've already looked at documentation and other examples, but I'm not able to clarify the problem.
swagger: '2.0'
info:
version: "1"
title: 'Grocery Shop'
description: 'This contains the url to access all the Grocery food related information. You can also add, update or delete any food item as well based on their respective id.'
contact:
email: you#your-company.com
tags:
- name: FoodItem
description: Specifically for Food item
- name: Category
description: Specifically for the category purpose
schemes:
- https
paths:
'/findfood/{foodItemId}':
get:
tags:
- FoodItem
summary: "Find the required food"
description: "Find the food with passed food id as an argument. Make sure that passed id exist otherwise it will return an error"
operationId: findFoodWithId
produces:
- "application/json"
parameters:
- in: path
name: foodItemId
required: true
type: integer
miniumum: 1
description: The id associated with the food in the grocery shop
responses:
200:
description: "successful operation"
schema:
$ref: '#definitions/Food'
404:
description: "Food is not found
definitions:
Food:
type: "object"
properties:
foodItemId:
type: integer
format: int32
required:
- foodItemId
xml:
name: "User"
# Added by API Auto Mocking Plugin
host: "localhost:8080"
basePath: "/grocery"
The errors which I'm getting are:
Semantic error at paths./findfood/{foodItemId} Declared path parameter
"foodItemId" needs to be defined as a path parameter at either the
path or operation level Jump to line 18
Schema error at paths./findfood/{foodItemId}.get.parameters[0] is not
exactly one from
<#/definitions/parameter>,<#/definitions/jsonReference> Jump to line
28
Parser error can not read a block mapping entry; a multiline key may
not be an implicit key Jump to line 48
These errors are misleading. The actual errors are:
miniumum: 1 contains a typo - miniumum
$ref: '#definitions/Food' needs a / between # and definitions: '#/definitions/Food'
description: "Food is not found needs the ending quotation mark.
I'm attempting to document a REST API using Swagger. Per REST API norms, I have endpoints for each Thing, and the GET protocols for each endpoint are bog standard normal: /thing/{id} returns a single Thing with the matching ID you give, and /thing/ returns a list of all valid Things.
The YAML for /thing/{id} is straightforward enough.
get:
operationId: GET_thing-id
tags:
- Thing
description: >-
Gets a specific Thing.
parameters:
- name: token
in: query
required: false
type: string
- name: Accept
in: header
required: false
type: string
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Thing'
Where the $ref refers to the following, further down the YAML file:
definitions:
Thing:
title: Thing
type: object
properties:
id:
type: string
description: uuid.
But I find myself unsure how to handle the /thing/ endpoint, which is supposed to simply return a list of the models above. There seems to be no clear way to do this from perusing the Swagger spec, which I have done in depth at this point. Does anyone have guidance on how to handle this?
I figured it out. The problem was that there's slightly different things I need to define for an array and that was a real issue in tracking it down. The solution is:
definitions:
ThingArray:
title: ThingArray
type: array
items:
$ref: '#/definitions/Thing'
This can then be used in the /thing/ path and it looks perfectly reasonable.
I'm preparing my API documentation by doing it per hand and not auto generated. There I have headers that should be sent to all APIs and don't know if it is possible to define parameters globally for the whole API or not?
Some of these headers are static and some has to be set when call to API is made, but they are all the same in all APIs, I don't want to copy and paste parameters for each API and each method as this will not be maintainable in the future.
I saw the static headers by API definition but there is no single document for how somebody can set them or use them.
Is this possible at all or not?
It depends on what kind of parameters they are.
The examples below are in YAML (for readability), but you can use http://www.json2yaml.com to convert them to JSON.
Security-related parameters: Authorization header, API keys, etc.
Parameters used for authentication and authorization, such as the Authorization header, API key, pair of API keys, etc. should be defined as security schemes rather than parameters.
In your example, the X-ACCOUNT looks like an API key, so you can use:
swagger: "2.0"
...
securityDefinitions:
accountId:
type: apiKey
in: header
name: X-ACCOUNT
description: All requests must include the `X-ACCOUNT` header containing your account ID.
# Apply the "X-ACCOUNT" header globally to all paths and operations
security:
- accountId: []
or in OpenAPI 3.0:
openapi: 3.0.0
...
components:
securitySchemes:
accountId:
type: apiKey
in: header
name: X-ACCOUNT
description: All requests must include the `X-ACCOUNT` header containing your account ID.
# Apply the "X-ACCOUNT" header globally to all paths and operations
security:
- accountId: []
Tools may handle security schemes parameters differently than generic parameters. For example, Swagger UI won't list API keys among operation parameters; instead, it will display the "Authorize" button where your users can enter their API key.
Generic parameters: offset, limit, resource IDs, etc.
OpenAPI 2.0 and 3.0 do not have a concept of global parameters. There are existing feature requests:
Allow for responses and parameters shared across all endpoints
Group multiple parameter definitions for better maintainability
The most you can do is define these parameters in the global parameters section (in OpenAPI 2.0) or the components/parameters section (in OpenAPI 3.0) and then $ref all parameters explicitly in each operation. The drawback is that you need to duplicate the $refs in each operation.
swagger: "2.0"
...
paths:
/users:
get:
parameters:
- $ref: '#/parameters/offset'
- $ref: '#/parameters/limit'
...
/organizations:
get:
parameters:
- $ref: '#/parameters/offset'
- $ref: '#/parameters/limit'
...
parameters:
offset:
in: query
name: offset
type: integer
minimum: 0
limit:
in: query
name: limit
type: integer
minimum: 1
maximum: 50
To reduce code duplication somewhat, parameters that apply to all operations on a path can be defined on the path level rather than inside operations.
paths:
/foo:
# These parameters apply to both GET and POST
parameters:
- $ref: '#/parameters/some_param'
- $ref: '#/parameters/another_param'
get:
...
post:
...
If you're talking about header parameters sent by consumer when calling the API...
You can at least define them once and for all in parameters sections then only reference them when needed.
In the example below:
CommonPathParameterHeader, ReusableParameterHeader and AnotherReusableParameterHeader are defined once and for all in parameterson the root of the document and can be used in any parameters list
CommonPathParameterHeaderis referenced in parameters section of /resources and /other-resources paths, meaning that ALL operation of these paths need this header
ReusableParameterHeader is referenced in get /resources meaning that it's needed on this operation
Same thing for AnotherReusableParameterHeader in get /other-resources
Example:
swagger: '2.0'
info:
version: 1.0.0
title: Header API
description: A simple API to learn how you can define headers
parameters:
CommonPathParameterHeader:
name: COMMON-PARAMETER-HEADER
type: string
in: header
required: true
ReusableParameterHeader:
name: REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
AnotherReusableParameterHeader:
name: ANOTHER-REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
paths:
/resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/ReusableParameterHeader'
responses:
'200':
description: gets some resources
/other-resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/AnotherReusableParameterHeader'
responses:
'200':
description: gets some other resources
post:
responses:
'204':
description: Succesfully created.
If you're talking about header sent with each API response...
Unfortunately you cannot define reusable response headers.
But at least you can define a reusable response containing these headers for common HTTP responses such as a 500 error.
Example:
swagger: '2.0'
info:
version: 1.0.0
title: Header API
description: A simple API to learn how you can define headers
parameters:
CommonPathParameterHeader:
name: COMMON-PARAMETER-HEADER
type: string
in: header
required: true
ReusableParameterHeader:
name: REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
AnotherReusableParameterHeader:
name: ANOTHER-REUSABLE-PARAMETER-HEADER
type: string
in: header
required: true
paths:
/resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/ReusableParameterHeader'
responses:
'200':
description: gets some resources
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
/other-resources:
parameters:
- $ref: '#/parameters/CommonPathParameterHeader'
get:
parameters:
- $ref: '#/parameters/AnotherReusableParameterHeader'
responses:
'200':
description: gets some other resources
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
post:
responses:
'204':
description: Succesfully created.
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
'500':
$ref: '#/responses/Standard500ErrorResponse'
responses:
Standard500ErrorResponse:
description: An unexpected error occured.
headers:
X-Rate-Limit-Remaining:
type: integer
X-Rate-Limit-Reset:
type: string
format: date-time
About OpenAPI (fka. Swagger) Next version
The OpenAPI spec (fka. Swagger) will evolve and include the definition of reusable response headers among other things (cf. https://github.com/OAI/OpenAPI-Specification/issues/563).
As per this Swagger issue comment, support for global parameters (including header parameters) is not planned in foreseeable future, but to limit the repetition you should use parameters references as in #Arnaud's answer (parameters: - $ref: '#/parameters/paramX').
also wish some global variables, can be used anywhere.
( even in some examples, so can change common settings globally in ui ).
something like
"hello ${var1}" in shell or javascript.
searched docs many times, not found solution yet.
: (