Swagger and JSON Patch - rest

I have the following object structure in my database
{
partnerName: '24 Fitness',
supportedProducts: [
'FitBit',
'Protein Powder'
]
},
where the key value supportedProducts can be modified from the client side.
I am constructing a PATCH API method using swagger documentation to support the above functionality. But I am unsure of the patch object definition, as documentation doesn't provide an detailed example of constructing a PATCH.
The current definition that I have ends up in error upon execution and looks like as following
"patch":{
"description":"Update supported products for a partner",
"operationId":"Update supported products",
"parameters":[
{
"name": "partnerName",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "supportedProducts",
"in": "body",
"required": true,
"schema":{
"$ref":"#/definitions/PatchRequest"
}
}
],
"responses":{
"200":{
"description": "product updated"
},
"404":{
"description": "Not Found"
}
}
"definitions": {
"PatchRequest":{
"type": "object",
"required":[
"partnerName",
"supportedProducts"
],
"properties":{
"partnerName":{"type": "string"},
"supportedProducts":{
"type": "array",
"items":{"type": "string"}
}
}
}
}

For this simple case, I would use a JSON Patch object to describe the operations to make on the target.
Here is an example of a JSON Patch Swagger API.
paths:
/users/{GUID}:
patch:
summary: Update a user
parameters:
- name: GUID
in: path
required: true
type: string
format: GUID
description: The GUID of a specific user
- name: JsonPatch
in: body
required: true
schema:
$ref: "#/definitions/PatchRequest"
responses:
'200':
description: Successful response
schema:
$ref: "#/definitions/User"
definitions:
PatchRequest:
type: array
items:
$ref: "#/definitions/PatchDocument"
PatchDocument:
description: A JSONPatch document as defined by RFC 6902
required:
- "op"
- "path"
properties:
op:
type: string
description: The operation to be performed
enum:
- "add"
- "remove"
- "replace"
- "move"
- "copy"
- "test"
path:
type: string
description: A JSON-Pointer
value:
type: object
description: The value to be used within the operations.
from:
type: string
description: A string containing a JSON Pointer value.

For OpenApi 3.0.x the structure of the .yaml file has changed. A valid definition could look like:
components:
requestBodies:
PatchBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PatchBody'
schemas:
PatchBody:
type: array
items:
$ref: "#/components/schemas/PatchDocument"
PatchDocument:
type: object
description: A JSONPatch document as defined by RFC 6902
required:
- "op"
- "path"
properties:
op:
type: string
description: The operation to be performed
enum:
- "add"
- "remove"
- "replace"
- "move"
- "copy"
- "test"
path:
type: string
description: A JSON-Pointer
value:
type: object
description: The value to be used within the operations.
from:
type: string
description: A string containing a JSON Pointer value.
patch:
parameters:
- $ref: '#/components/parameters/objectId'
requestBody:
$ref: '#/components/requestBodies/PatchBody'
responses:
...

Since the JSON Patch format is well defined by RFC 6902 I think it would be sufficient (at least for OpenAPI 3) to specify the content type defined in the RFC, and since it seems to be necessary to define either a schema or example (at least in my swagger editor), to also specify type: string and format: JSON Patch or format: RFC 6902.
It doesn't make sense to redefine a format that is already well defined by the RFC.
Example:
paths:
/users/{GUID}:
patch:
summary: Update a user
parameters:
- name: GUID
in: path
required: true
type: string
format: GUID
description: The GUID of a specific user
requestBody:
content:
application/json-patch+json:
schema:
type: string
format: RFC 6902

Related

OpenApi / Swagger v3 Question around Using References by Id instead of Object

I'm trying to determine how I can set up a request in a manner that makes it easier for end users to interact with it:
so given that Pet is defined as such:
#/components/schemas/Pet
Pet:
x-swagger-router-model: io.swagger.petstore.model.Pet
required:
- name
properties:
id:
type: integer
format: int64
example: 10
name:
type: string
example: doggie
category:
$ref: '#/components/schemas/Category'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
type: object
ApiResponse:
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
type: object
and Category is defined as:
#/components/schemas/Category
x-swagger-router-model: io.swagger.petstore.model.Category
properties:
id:
type: integer
format: int64
example: 1
name:
type: string
example: Dogs
xml:
name: category
type: object
and the way to add a new object is by using this POST:
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: Add a new pet to the store
operationId: addPet
responses:
'200':
description: Successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
description: Create a new pet in the store
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Pet'
How do i generate a POST with this format:
{
"id": 10,
"name": "doggie",
"category": 1,
"status": "available"
}
instead of this:
{
"id": 10,
"name": "doggie",
"category": {
"id": 1,
"name": "Dogs"
},
"status": "available"
}
I understand that I can set up a different schema for POST by specifying that for this type of request i would use an int for the category, but was hoping there would be a way to maintain the appropriate referencing of the pet.category to the category.
any ideas would be appreciated.
ps note that the reference for this example is directly accessible here

openapi 3.0: how to add examples of objects having nested objects inside it?

I want to add examples of my response schema in openapi 3.0 YAML. I have went through the idea on link https://swagger.io/docs/specification/adding-examples/ but my issue is that my response schema object contains nested objects inside it. Can anyone help and guide me about how to add example while having nested objects?
You can define a response example in two ways.
Let this is your nested json object response :
{
"status": true,
"data": {
"storeId": "string",
"message": "string"
}
}
Method 1 : Here in parameter definition itself you can add the example
myschema:
type: object
properties:
status:
type: boolean
required: true
example: true
data:
type: object
properties:
"message":
type: string
example: Success
"Id":
type: string
example: 1234
Method 2 : Here after the property definition you can define an example: tag like this
myschema:
type: object
properties:
status:
type: boolean
required: true
data:
type: object
properties:
message:
type: string
Id:
type: string
example:
status: true
data:
Id: '1234'
message: success

Mule#4: RAML not able to parse JSON in escape characters

I have following schema declared in RAML 1.0
body:
application/json:
type: object
properties:
region:
example:
strict: false
value: NA
type: string
required: true
country:
description: Country name
example:
strict: false
value: US
type: string
required: true
orders:
type: array
items:
properties:
orderName:
example:
strict: false
value: "toys"
type: string
maxLength: 20
required: false
orderNumber:
example:
strict: false
value: order12
type: string
maxLength: 25
required: false
maxItems: 100
required: true
When I am sending the below JSON request
{
"region": "South America",
"country": "US",
"orders": [
"{\n \"orderNumber\": \"ORD0118\",\n \"orderName\": \"toys\"\n}",
"{\n \"orderNumber\": \"ORD0119\",\n \"orderName\": \"pens\"\n}",
"{\n \"orderNumber\": \"ORD0120\",\n \"orderName\": \"pencils\"\n}"
]
}
In batch when I am aggregating message and concatenating the payload, the payload was getting formatted as above.
I am seeing a bad request error
Position: Line 0, Column 0\n/orders/0 expected type: JSONObject, found: String Location: Position: Line 0, Column 0\n/orders/1 expected type: JSONObject, found: String Location: Position: Line 0, Column 0\n/orders/2 expected type: JSONObject, found: String Location: Position: Line 0, Column 0",
Please help me in updating RAML to accept the JSON in escape characters as well.
The payload's orders attribute is a list of strings, not of objects, because the members of the array are 'escaped'. Depending on what you intend to do, you can change the RAML to set the array to an array of strings, or convert somehow the strings to the objects the RAML expects.
For the former replace the definition of orders by something like:
orders:
type: string[]
If you want to do the later the following DataWeave script will transform the list in the expected objects:
%dw 2.0
output application/json
---
{
region: payload.region,
country: payload.country,
orders: payload.orders map read($,"application/json")
}
Output:
{
"region": "South America",
"country": "US",
"orders": [
{
"orderNumber": "ORD0118",
"orderName": "toys"
},
{
"orderNumber": "ORD0119",
"orderName": "pens"
},
{
"orderNumber": "ORD0120",
"orderName": "pencils"
}
]
}
Enabling the preserve MIME types in batch aggregator solved this issue.

How to define an unwrapped response in OpenAPI?

I have this component:
components:
schemas:
book:
type: object
required:
- id
properties:
id:
type: string
title:
type: string
author:
type: string
Is there a way to define a response object that includes the book attributes using this component? The response is this:
{
"id": "xxxxx",
"title": "This is title",
"author": "John"
}
I tried like this:
responses:
200-response:
description: HTTP 200 response
content:
application/json:
schema:
type: object
properties:
book:
$ref: '#/components/schemas/book'
but it has the parent object of book instead of the attributes immediately.
You're almost there. Just put the schema $ref directly under schema.
responses:
200-response:
description: HTTP 200 response
content:
application/json:
schema:
$ref: '#/components/schemas/book'

Specify an array as a parameter with Swagger

How do I specify an array as a parameter? For instance, post to /persons can be given strings username, firstname, and lastname, and array myArray.
paths:
/persons:
post:
parameters:
- name: person_what_is_the_purpose_of_this
in: body
description: The person to create.
schema:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
myArray:
type: array
items:
properties:
myArrayElement:
type: string
responses:
200:
description: A list of Person
schema:
type: array
items:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
swagger: "2.0"
info:
version: "1.0.0"
title: Swagger Petstore
host: petstore.swagger.io
basePath: /v2
schemes:
- http
paths:
/pets/findByStatus:
get:
parameters:
- in: query
name: status
type: array
items:
type: string
responses:
"200":
description: successful operation
schema:
type: array
items:
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
name:
type: string
example: doggie
photoUrls:
type: array
items:
type: string
tags:
type: array
items:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
"400":
description: Invalid status value
You need to specify collectionFormat: multi
For your array it would look like this, be sure to put it on the same level as the type:
myArray:
type: array
collectionFormat: multi
Documentation about arrays