How do I express JSON-API sparse fieldsets with OpenAPI-3.0 - openapi

I'm implementing an OpenAPI-3.0 spec for my API, and I plan on using sparse fieldsets as a parameter for GETs. The examples for parameters using style=deepObject are a little sparse, so I'm not sure if I've got this exactly right.
- in: query
name: fields
style: deepObject
schema:
type: object
additionalProperties:
type: string
Can I combine both the deepObject and additionalProperties options?
I want to support flexible query parameter inputs like this:
GET /articles?include=author&fields[articles]=title,body&fields[people]=name
but I don't want to have to spell out every single option for each resource and field.

Your definition is correct. You might also need to add allowReserved: true so that the comma in =title,body is not percent-encoded, and you can add a parameter example value for documentation purposes:
- in: query
name: fields
style: deepObject
allowReserved: true
schema:
type: object
additionalProperties:
type: string
example:
articles: title,body
people: name
When using "try it out" in Swagger UI, enter the parameter value in the JSON format like so:
{
"articles": "title,body",
"people": "name"
}
Swagger UI will serialize the parameter as
?fields[articles]=title,body&fields[people]=name

Related

How to define a header parameter with multiple attributes in OpenAPI 3.0?

I need to define a header parameter like this X-Custom: id1=uuid1;id2=uuid3
Since this is a common header for all paths I want to define it once and reference it every time. So far I came up with this:
openapi: 3.0.3
components:
parameters:
customHeader:
name: "X-Custom"
in: header # <--- produces error
required: true
schema:
type: object
properties:
id1:
type: string
format: uuid
id2:
type: string
format: uuid
style: matrix
explode: true
But I get an error that 'header' is not allowed and the parameter does not show up in the preview.
Any idea what's wrong?
OpenAPI 3 supports only style: simple for header parameters. This means that objects can be serialized in one of two ways:
# {"id1": "uuid1", "id2": "uuid2"} becomes...
# explode: false
X-Custom: id1,uuid1,id2,uuid2
# explode: true
X-Custom: id1=uuid1,id2=uuid2
Note that none of these styles match your expected format X-Custom: id1=uuid1;id2=uuid2 with ; as a separator. In fact, OpenAPI currently does not have a way to define ;-separated header values.
The most you can do is define the entire header as a string, mention the header value format in the description, and provide an example value:
customHeader:
name: X-Custom
in: header
required: true
schema:
type: string
example: id1=uuid1;id2=uuid2
There are existing feature requests to improve header serialization styles in OpenAPI:
Support for structured-headers de/serialization
Make it easier to define link headers
If you are designing a new API rather than documenting an existing one, another workaround is to split the header into two headers:
X-id1: uuid1
X-id2: uuid2

How to specify an unknown number of a parameter in the response Open API

I'm trying to model my API using swagger and the Open API 3.0 specification. I have made some schemas and now I'm modeling the response of my endpoints. The problem is that they return something like this:
[
{
"name": "this attribute is always here"
"type1": { "description": "this maybe appear or not" },
"type2": { "description": "this maybe appear or not" },
...
"typeN": { "description": "N is not a fixed number, it may range from 0 to another positive integer" },
}
]
I know how to model the array and the object (with the name property). The problem comes when I have to model the typeX properties, I do not know how to specify that they are optional and the number of ocurrences is variable. Any idea?
This object is basically a string-to-object dictionary/hashmap with an extra name property. Fixed properties are defined in properties, and the dictionary part can be defined using either patternProperties (in OpenAPI 3.1) or additionalProperties (in OpenAPI 3.0 and 2.0).
OpenAPI 3.1
In OAS 3.1 your object can be defined as follows. Since the optional property names all follow the typeX format, the schema uses patternProperties to define the regex for the property names.
MyObject:
type: object
required: [name]
properties:
name:
type: string
patternProperties: # <-- This part defines the "typeX" properties
^type\d+$: # <-- Property name regex
type: object # <-- Property value
properties:
description:
type: string
additionalProperties: false # No other properties other than "name" and "typeX"
OpenAPI 3.0 and 2.0
In earlier OAS versions, you use additionalProperties to define "may have extra properties with <such> values", but there's no way to define the format of those property names. You can however mention the property name format in the schema description and also add a schema example for documentation purposes.
MyObject:
type: object
description: >-
In addition to the `name` property, this object may have an arbitrary
number of properties named `typeX` where X is a positive integer.
required: [name]
properties:
name:
type: string
additionalProperties:
# This part defines the *value* of the typeX properties
type: object
properties:
description:
type: string
# Optional schema example
name: something
type1:
description: ....
type2:
description: ....

OpenApi 3.0 string array inside body

In OpenApi 3.0 how do I pass string array inside requestBody?
I'm able to pass it as member of class, but since it is class with one field only, I'm looking for simpler solution.
When using:
requestBody:
content:
'*/*':
schema:
type: array
items:
type: string
required: true
I get error 415.
Looks like using application/json content does the trick. Although string array is not a typical json, it is treated as one.

Canvas PowerApp Form unable to get fields from Custom Connector returning tabular data from REST API

I created a Custom Connector our of my REST API that returns tabular data. I used it as a datasource in a canvas powerapp, which store the records from the custom connector into a collection. This collection is used as datasource by a Gallery which successfully displays the items and attributes of each item. However, when I try to create an Edit Form that uses the collection as datasource it cannot access the fields. It does not work using directly the custom connector as data source either.
In this answer from #aorphan I read that you can use custom connectors in forms as long as they return tables instead of actions. And as far as I can see, the content of the collection is tabular data:
Even the columns of the collection can be accessed as attributes of the item displayed by the Gallery:
However, even after setting the collection as datasource of a new Edit Form, it is unable to add any fields from the datasource:
Just in case my data needs some richer definition to be correctly interpreted by the Form, the JSON returned by my API looks like this:
{
"quotes": [
{
"quote_pk": 347,
"shipment_name": "test add leg",
"organization_ff_name": "LIFE",
"quote_id": "1234",
"effective_until": "2020-05-10",
"eta": "2020-05-14T12:00:00Z",
"price": 100.0,
"quote_status": 2
},
{
"quote_pk": 345,
"shipment_name": "test modal review",
"organization_ff_name": "LIFE",
"quote_id": "123",
"effective_until": "2020-05-11",
"eta": "2020-05-22T12:00:00Z",
"price": 1749.94,
"quote_status": 6
}
]
}
And the definition of my Custom Connector goes like this:
swagger: '2.0'
info: {title: some title, description: some description, version: '1.0'}
host: server.domain.com
basePath: /organizations/endpoint/
schemes: [https]
consumes: []
produces: []
paths:
/organizations/endpoint/shipment_quotes/: {}
/shipment_quotes/:
get:
responses:
'200':
description: default
schema:
type: object
properties:
quotes:
type: array
items:
type: object
properties:
quote_pk: {type: integer, format: int32, description: quote_pk}
shipment_name: {type: string, description: shipment_name}
organization_ff_name: {type: string, description: organization_ff_name}
quote_id: {type: string, description: quote_id}
effective_until: {type: string, description: effective_until}
eta: {type: string, description: eta}
price: {type: number, format: float, description: price}
quote_status: {type: integer, format: int32, description: quote_status}
description: quotes
summary: peration summary
description: operation description
operationId: operationId
parameters:
- {name: Content-Type, in: header, required: false, type: string}
- {name: Accept, in: header, required: false, type: string}
definitions: {}
parameters: {}
responses: {}
securityDefinitions: {}
security: []
tags: []
Please help me to get the datasource right so the form be able to add its fields, or at least let me know in case this is not possible for some reason so I can move on.
Formally, Collections cannot be used as a DataSource for Form controls in PowerApps. You're efforts are admirable and it looks like you've tried just about everything, so I'll pass my little secret.
Its probably not officially supported so use at your own risk.
Create a Collection of the response from your Custom Connector (which you've done)
Add a Gallery control and set its Items property to the Collection (which you've already done)
Add an Edit Form control and set its DataSource property to the Collection (which you've already done)
Click the three little dots and Add Custom Card
Add a TextBox control to the Custom Card.
Set the TextBox Default property to gallery.Selected.X where "X" is the value you want to edit in the form.
Repeat steps 4-7 for each form field you wish to capture.
Create a "Submit" button in the Form which Patches/UpdateIf's the Collection then calls your POST (or PUT) method from the Custom Connector to patch the edits back to your DataSource.
8a. I only see a GET request in your swagger file. You'll (obviously) need a POST/PUT to get the data from the Collection back up to your DataSource.
8b. This little "wrapper" is likely what PowerApps handles for you when you use an "approved" DataSource for a Form control.
Note: Your Form will show "No data source" in the PowerApps studio, but your user won't see it.
Here it is in action:
Help much?

Specify an array of strings as body parameter in swagger API

I would like to post an array of strings like
[
"id1",
"id2"
]
to a Swagger based API. In my swagger file, I have those lines:
paths:
/some_url:
post:
parameters:
- name: ids
in: body
required: true
What is the correct way to specify the type of ids as an array of strings?
Update:
According to the specification, the following should work in my option:
parameters:
- in: body
description: xxx
required: true
schema:
type: array
items:
type: string
https://github.com/Yelp/swagger_spec_validator does not accept it and returns a long list of convoluted errors, which look like the code expects some $ref.
Your description of an array of string is correct, but the parameter definition misses the name property to be valid.
Here's a full working example:
swagger: "2.0"
info:
title: A dummy title
version: 1.0.0
paths:
/path:
post:
parameters:
- in: body
description: xxx
required: true
name: a name
schema:
type: array
items:
type: string
responses:
default:
description: OK
Try the online editor to check your OpenAPI (fka. Swagger) specs: http://editor.swagger.io/
I have created a swagger issue as the help provided by Arnaud, although is valid yaml, will give you NPE exceptions when trying to generate. You will need to provide an object like the following:
myDataItem:
type: object
description: A list of values
required:
- values
properties:
values:
type: array
items:
type: string
And then refer to it (in your post item etc):
schema:
$ref: "#/definitions/myDataItem"
For reference the github issue:
https://github.com/swagger-api/swagger-codegen/issues/6745
Note, the issue has been fixed in version 2.3.0 and higher, ideally you should upgrade to that version.
None of the answers worked for me. As it is stated in the following Baeldung article:
To better document the API and instruct the user, we can use the example label of how to insert values
So the full working example would be something like that:
swagger: "2.0"
info:
title: A dummy title
version: 1.0.0
paths:
/path:
post:
parameters:
- in: body
description: xxx
required: true
name: a name
schema:
type: array
items:
type: string
example: ["str1", "str2", "str3"]
responses:
default:
description: OK
You can check how the Example Value is now better informed in the Swagger editor.
For Array containing Object as it's content, definition for Object can be also expressed using definitions & $ref.
Example:
schema:
type: array
items:
$ref: '#/definitions/ObjectSchemaDefinition'
definitions:
ObjectSchemaDefinition:
type: string
The answer with the most votes got me in the right direction. I just needed an example of an array of objects where each one of them had a property which was an array of strings with more than one value in the strings array. Thanks to the documentation I got it working like this:
MyObject:
type: object
properties:
body:
type: array
items:
type: object
properties:
type:
type: string
values:
type: array
items:
type: string
example:
- type: "firstElement"
values: ["Active", "Inactive"]
- type: "SecondElement"
values: ["Active", "Inactive"]
One thing to keep in mind is that indentation is of paramount importance to swagger. If you don't indent things well, swagger will give you strange error messages.