Can I specify the response directly in Swagger 2.0? - swagger

I am defining my response as per:
responses:
200:
description: 'An authProvider object'
schema:
type: 'array'
items:
$ref: '#/definitions/AuthProvider'
Is it possible for me to directly attach another field or 2 in the response? I would like to add something that I don't want to put into AuthProvider

Whenever $ref is used, it's basically using JSON Reference. By definition (see linked spec), anything defined within the same object as the reference itself is ignored. As such, it is not possible to directly add additional properties alongside with the $ref definition.
That said, you can use composition to 'combine' two objects into one. This is done using the allOf JSON Schema directive. A simple example for such a definition would look like this:
allOf:
-
$ref: "..."
-
properties:
property1:
type: "string"
property2:
type: "boolean"
Note 1: The various Swagger tools out there may not fully support composition at the moment.
Note 2: As always, it's normally better to externalize the definition (even if used only once) rather than being defined inline.

Related

How to define an array[object] parameter correctly in the query string - OAS 3.0

I have a few issues with an array[object] query string definition in OpenAPI 3.0.3:
parameters:
- in: query
name: find
content:
application/json:
schema:
type: array
items:
type: object
minItems: 1
maxItems: 1
properties:
$match:
type: object
description: To specify conditions to filter the result.
properties:
name:
type: string
description: Name of the desired import
1 - Even though I have specified that the array can only have 1 item, Swagger UI allows me to add multiple items.
2 - It seems that Swagger UI doesn't encode the content properly or the way I want it. When I call my function in my code, I pass the parameter after stringifying (JSON.stringify()) and it is sent like below in the URL:
[{%22$match%22:{%22name%22:%22ffghhhjjj%22}}]
which is deserialized correctly: [{"$match":{"name":"ffghhhjjj"}}"]
But when I see the URL in Swagger UI, it is different:
https://.../api/contact-service/v1/imports?find=%5B%22%7B%5C%22%24match%5C%22%3A%7B%5C%22name%5C%22%3A%5C%22ffghhhjjj%5C%22%7D%7D%22%5D&limit=2&skip=0
This is how the parameter looks like after decoding:
["{\"$match\":{\"name\":\"ffghhhjjj\"}}"]
As you can see, it has sent the array item as string as it should be an object or that the whole value should have been in string that it can be deserialized correctly on the server side.
3 - Another problem is that even though I defined the description for my object's properties, Swagger UI doesn't show it. Defining parameters under components also won't show them as it does for the schemas. Any idea that how I can give the user hints about different properties in my parameter object? I need description to explain different ways that the user can fill up the filter. I.e., "name" can be specified in different formats for filtering:
{"name": "item-name"}
to just items with the specified name), OR:
"name": {"$in": ["name-1","name-2"]}
to get all items that their names matches one of the specified names.
I have tried to place minItems and maxItems in the different locations but didn't work. The current location doesn't give me any errors. Also, I have tried to remove the content and application/json properties but didn't make any changes.

open API, I want to add description to remote schema

I reference an external schema for a property but I want to add my own description.
myProp:
allOf:
- $ref: "https://opensource.zalando.com/problem/schema.yaml#/Problem"
- type: object
Swagger editor tells me
Could not resolve reference: Could not resolve pointer /Problem does not exist in document
It looks like it will only allow allOf, for locally defined objects. Is that correct?

How do I refer between different APIs in SwaggerHub?

I am working with SwaggerHub and OpenAPI 3.0.0. I have two APIs in SwaggerHub.
The first has got following access link:
https://app.swaggerhub.com/apis/myapipath/1.0.0 and contains a definition named components/schemas/ApiOffer.
In the second API, I want the property offer to be a $ref to that definition. I use:
components:
schemas:
Offerers:
type: object
required:
- offererId
- overview
properties:
offererId:
$ref: '#/components/schemas/OfferersId'
overview:
$ref: '#/components/schemas/OfferersOverview'
offer:
$ref: 'https://app.swaggerhub.com/apis/myapipath/1.0.0#/components/schemas/ApiOffer'
but get the following error:
"Could not resolve reference because of: Could not resolve pointer:
/components/schemas/ApiOffer does not exist in document"
even though the /components/schemas/ApiOffer definition exists.
How do I correct my reference so that it points to the other API?
References to SwaggerHub definitions must use the hostname API.swaggerhub.com instead of APP.swaggerhub.com.

When should I use $ref versus the object id in Open API

I'm working on a schema in OpenAPI with Swagger, and I'm not sure if I'm misusing the $ref element. I have a User model and a Project model, similar to something like
User:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
...
Project:
type: object
properties:
id:
type: string
user_id:
$ref: "#/components/schemas/User"
...
I don't see much in the Open API Spec documentation as to what the $ref element is specifically, but in the JSON Schema documentation—of which Open API extends the $ref element—I've found the following description of the item:
The easiest way to describe $ref is that it gets logically replaced with the thing that it points to.
In the case above, I just want to refer to the user who posted a project. It seems unnecessary to essentially include all of the information about the User in the Project model if that is what it's doing. Would it be better practice to just have a string element of the uuid of the user_id? Or is it correct as is? Is it more common to name the field user rather than user_id if that is the case?
Edit:
I realize the heart of what was bothering me is if there were to be recursive references. If a User has an array of $ref to Projects, but also a Project has an array of $ref to Users, the replacement (if that's what it's doing) would infinitely embed each model in the other. I assume this wouldn't happen in practice, assuming that a $ref is just a pointer to the Model?
In your example it might make sense to extract the userId definition into its own schema (assuming it is the userId only that appears, not an entire User object), then it is clearer what's going on:
components:
schemas:
User:
type: object
properties:
id:
$ref: '#/components/schemas/userId'
name:
type: string
...
Project:
type: object
properties:
id:
type: string
user_id:
$ref: "#/components/schemas/userId"
...
userId:
type: string
format: uuid
But there is nothing stopping you creating a direct $ref to #/components/schemas/User/properties/id instead, as long as what is pointed to is a valid OpenAPI schemaObject.
Circular references are allowed by the JSON Reference and OpenAPI specifications, so your analogy of a pointer is a sound one.

Using different Swagger Models properties for collection/detail request/response

I'm beginner of Swagger, and I'm trying to define endpoints which have:
Some read-only properties that isn't allowed in request but show in response
Some white-only properties and hidden that allowed in request but not show in response
Some properties only on collection level at /resources, but some other additional details on /resources/resource-id
What I'm doing is defining the following models:
ResourceBaseModel: this saves all the shared properties of all
ResourceBaseModel:
type: object
properties:
shared_properties:
type: string
ResourceCollectionResponse: this is wrapping the response additional properties
ResourceCollectionResponse:
type: array
items:
type: object
allOf:
- $ref: ResourceBaseModel
- type: object
properties:
collection_normal_properties:
type: string
collection_read_only_properties:
type: string
readOnly: true
ResourceDetailResponse: this is adding different properties for response
ResourceDetailResponse:
type: object
allOf:
- $ref: ResourceBaseModel
- type: object
properties:
detail_normal_properties:
type: string
detail_read_only_properties:
type: string
readOnly: true
ResourceRequest: same, add additional and write-only properties
ResourceRequest:
type: object
allOf:
- $ref: ResourceBaseModel
- type: object
properties:
request_write_only_properties:
type: string
This is making every model defined 4 times and I feel it's not efficient.
So here are my questions:
I saw there is a discriminator in Swagger Spec. Should I use this with "allOf" of these extended models? From result, using of not using this discriminator, the result looks the same as long as "allOf" used.
the "readOnly", if defined in base level, still shows in Swagger UI and needs special handling or filtering when using or generating docs. The demo data in request is also showing these readOnly properties in Swagger UI request (but only the model added a label of "read-only"). Is there any better solution besides what I'm trying.
the "white-only", as far as I know, is not supported. Is defining a new model the only way?
I wonder if there will be one day I can define only one model to describe all of the models, or do you think an innovative language that can compile to Swagger YAML can benefit the whole community? Like how Sass/LESS builds CSS?
Thanks for your help and insightes!
OpenAPI 3.0.x supports writeOnly as well as readOnly schema properties. This should allow you to simplify your models, the allOf / discriminator should not be necessary.

Resources