I'm using the nestjs swagger module and want to create my API documentation. For endpoints relying on the request body I can assign a DTO class to the docs like
#ApiBody({ type: CreateUserDTO })
Some endpoints also rely on the request params or queries. For params I would do something like
#ApiParam({ type: GetUserByIdDTO })
(I know this is a bad example because there is no need for a DTO for a user id but let's assume you want to validate your params with a DTO class using class-validator)
but I'm getting this error
Argument of type '{ type: typeof GetUserByIdDTO; }' is not assignable
to parameter of type 'ApiParamOptions'. Property 'name' is missing
in type '{ type: typeof GetUserByIdDTO; }' but required in type
'ApiParamMetadata'.
For queries I would do something like
#ApiQuery({ type: GetUsersDTO })
and get this error
Argument of type '{ type: typeof GetUsersDTO; }' is not assignable to
parameter of type 'ApiQueryOptions'. Property 'name' is missing in
type '{ type: typeof GetUsersDTO; }' but required in type
'ApiQueryMetadata'.
So the APIBody decorator seems to work fine but how can I fix my APIParam and APIQuery decorators?
#ApiQuery and #ApiParam are needed when working with named params / query, like #Query('pageSize') o #Param('id'). In this case NestJS Swagger module should extract information directly from the DTO object specified, like:
async findElements(#Query() query: ElementsQueryDto) {
// ...
}
An important thing to note is that Dtos should be classes, not interfaces.
Related
I don't see any good documentation about how to execute GraphQL APIs using F# with Http.fs
Kindly share if you have the correct syntax available or point to the correct documentation for the same. I was trying with the Star Wars API given here: https://www.rithmschool.com/blog/an-introduction-to-graphql-queries
URL: https://swapi.graph.cool
Header: 'Content-Type': 'application/json'
JSON Body:
query {
Film (title:"A New Hope" ) {
director
characters {
name
}
}
}
Expected Response same as: https://swapi.graph.cool/
I'm not familiar with Http.fs, but here is a small working example of calling the API using the F# Data Http utility:
Http.RequestString
( "https://swapi.graph.cool",
httpMethod="POST", headers=[ HttpRequestHeaders.ContentType("application/json") ],
body=TextRequest("{\"query\": \"{ allFilms { title } }\"}") )
The main thing is that the body needs to be a JSON value where the actual query is a string stored in a record with a field named "query", i.e. {"query": "...."}.
Seem to almost have it...
Trying to have swagger send an anonymous hash of parameters in the request body.
I have an anonymous hash containing one key named list that contains an array.
Trying to send this parameter (text/json):
{
list : [ 'string1', 'string2' ]
}
Swagger is building the right curl statement but is not sending the parameters via the UI.
Swagger builds this (works from command line):
/usr/bin/curl -H 'Content-Type: text/json' -X GET -d '{ "list" : [ "text:/export/home/ihome/perl5/our_modules/check_parse_lib_rest/t/data/hosts:/export/home/ihome/perl5/our_modules/check_parse_lib_rest/t/data/hosts", "text:/export/home/ihome/perl5/our_modules/check_parse_lib_rest/t/data/hosts:/export/home/ihome/perl5/our_modules/check_parse_lib_rest/t/data/hosts.1" ] }' 'https://localhost.localdomain:9086/library/check_diff_batch'
But Swagger-ui shows no model example and sends no parameters in the request body.
In the editor I see it the list shows as undefined.
Schema
⇄
Comparison {
list:
ComparisonList undefined *
}
Definition -
paths:
/check_diff_batch:
get:
summary: Compare a list of file comparrison objects using diff.
description: |
FIXME: Takes an array of colon delimited comparrison objects.
Required parameter Comparrison object format = type:file1:file2
**RC** will return false if there are differences or a failure.
**FAULT_MSG** will return No Faults or a failure message.
parameters:
- $ref: "#/parameters/ComparrisonList"
responses:
200:
description: Successful response
examples:
text/json:
...
parameters:
ComparrisonList:
name: list
in: body
description: List of comparrison objects
schema:
$ref: "#/definitions/Comparisons"
definitions:
Comparisons:
required:
- list
properties:
list:
$ref: "#/definitions/ComparisonList"
ComparisonList:
additionalProperties:
type: string
additionalProperties is used to define associative arrays / hashmaps, not regular arrays. A regular string array is defined as:
definitions:
ComparisonList:
type: array
items:
type: string
You should also use a post operation and not get, since request body in GET does not have defined semantics as per RFC 7231 section 4.3.1.
How to specify a property as null or a reference? discusses how to specify a property as null or a reference using jsonschema.
I'm looking to do the same thing with swagger.
To recap the answer to the above, with jsonschema, one could do this:
{
"definitions": {
"Foo": {
# some complex object
}
},
"type": "object",
"properties": {
"foo": {
"oneOf": [
{"$ref": "#/definitions/Foo"},
{"type": "null"}
]
}
}
}
The key point to the answer was the use of oneOf.
The key points to my question:
I have a complex object which I want to keep DRY so I put it in a
definitions section for reuse throughout my swagger spec: values of other properties; response objects, etc.
In various places in my spec a
property may be a reference to such an object OR be null.
How do I specify this with Swagger which doesn't support oneOf or
anyOf?
Note: some swagger implementations use x-nullable (or some-such) to specify a property value can be null, however, $ref replaces the object with what it references, so it would appear any use of x-nullable is ignored.
OpenAPI 3.1
Define the property as anyOf of the $ref and type: 'null'.
YAML version:
foo:
anyOf:
- type: 'null' # Note the quotes around 'null'
- $ref: '#/components/schemas/Foo'
JSON version:
"foo": {
"anyOf": [
{ "type": "null" },
{ "$ref": "#/components/schemas/Foo" }
]
}
Why use anyOf and not oneOf? oneOf will fail validation if the referenced schema itself allows nulls, whereas anyOf will work.
OpenAPI 3.0
YAML version:
foo:
nullable: true
allOf:
- $ref: '#/components/schemas/Foo'
JSON version:
"foo": {
"nullable": true,
"allOf": [
{ "$ref": "#/components/schemas/Foo" }
]
}
In OAS 3.0, wrapping $ref into allOf is needed to combine the $ref with other keywords - because $ref overwrites any sibling keywords. This is further discussed in the OpenAPI Specification repository: Reference objects don't combine well with “nullable”
Not easy to do that. Even almost impossible. Your options :
Wait
There is a very long discussion about this point, maybe one day it will be done...
Use vendors extensions
You can use vendors extensions like x-oneOf and x-anyOf. I have already taken this hard way: You must to upgrade all used 'swagger tools' to take into account these vendors extensions.
In my case, we needed 'only' to :
Develops our own Jax-RS parser with customized annotations in order to extract swagger API file from sources
Extends swagger-codegen to take into account these extensions to generate java code for our clients
Develops our own swagger-ui: to facilitate this work, we added a preprocessing step to convert our swagger schema with our extensions to a valid json schema. It's easier to find a module to represent json schemas than swagger schemas in javascript. By cons we gave up the idea to test the API with the 'try it' button.
It was a year ago, maybe now ...
Refactor your APIs
Many projects don't need anyOf and oneOf, why not us ?
For OpenAPI 3.0 for some reason using nullable: true followed by allOf didn't work for the OpenAPI interpreter I'm using. As a workaround I ended up defining a must-be-null ref called null_type that I can use in an anyOf construct.
Like so:
allOf:
- anyOf:
- $ref: "#/components/schemas/null_type"
- $ref: "#/components/schemas/your_ref"
- description: "optionally add other properties here..."
where:
schemas:
null_type:
title: "OpenAPI 3.0 null-type ref"
description: "for adding nullability to a ref"
enum: [null]
your_ref:
...
I have a GET route where I would like to encode an object parameter in the url as a query string.
When writing the swagger documentation I basically get errors that disallow me to use schema/object types in a query type parameter:
paths:
/mypath/:
get:
parameters
- in: path
name: someParam
description: some param that works
required: true
type: string
format: timeuuid #good param, works well
- $ref: "#/parameters/mySortingParam" #this yields an error
parameters:
mySortingParam
name: paging
in: query
description: Holds various paging attributes
required: false
schema:
type: object
properties:
pageSize:
type: number
cursor:
type: object
properties:
after:
type: string
format: string
The request query param having an object value would be encoded in an actual request.
Even though swagger shows an error at the top of the screen the object is rendered correctly in the swagger UI editor, however with that error floating on top of the documentation.
I don't think you can use "object" as query parameter in Swagger spec as query parameter only supports primitive type (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types)
This is now possible with OpenAPI 3.0.
parameters:
- in: query
name: values
schema:
type: object
properties:
genre_id:
type: integer
author_id:
type: integer
title:
type: string
example:
{
"genre_id": 1,
"author_id": 1
}
style: form
explode: true
Here you can use style and explode keywords to specify how parameters should be serialised.
style defines how multiple values are delimited. Possible styles depend on the parameter location – path, query, header or cookie.
explode (true/false) specifies whether arrays and objects should
generate separate parameters for each array item or object property.
For the above example the url will be:
https://ebookstore.build/v1/users/books/search?genre_id=1&author_id=1
For more information on describing parameters with OpenAPI v3 and parameter serialisation, please refer here.
This is possible, just not with OpenAPI 2.0. OpenAPI 3.0 describes how this is possible here:
https://swagger.io/docs/specification/describing-parameters/
parameters:
- in: query
name: filter
# Wrap 'schema' into 'content.<media-type>'
content:
application/json: # <---- media type indicates how to serialize / deserialize the parameter content
schema:
type: object
properties:
type:
type: string
color:
type: string
In the meantime you could just have the query parameter as a plain old string type and then perform the serialization manually, then set the query parameter as required. This is what I'm doing until Swagger UI fully supports OpenAPI 3.0.
I get an error when I call Put to my server using WebApi Odata v4.
{
"error": {
"code": "",
"message": "The request is invalid.",
"innererror": {
"message": "job : The property 'test' does not exist on type 'Model.Temp'. Make sure to only use property names that are defined by the type.\r\n",
"type": "",
"stacktrace": ""
}
}
}
this error happens because the property "test" is not set in the Model "Temp". it is actually added by javascript, and only used in client-side
How do I make so that OData will just ignore properties that are not available in the Model ?
There is a way to deal with your scenario. It is not to ignore the properties, but to accept them by defining the entity type as an open type so that it can accept dynamic properties which are not defined in the model from the client and store them for future queries if necessary.
You can find the following tutorial for implementing an open type support: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/use-open-types-in-odata-v4