I'm trying to write a client to a large non Swagger-documented API and thought that writing the swagger.json
for it and using AutoRest would be a good way to accomplish that. The case is that this API wraps each operation's
response data into a larger object with control information, like this:
{
"resp_code": "SUCCESS",
"caller_ref": "2016111116233156169531",
"server_ref": "2016111116233189512798",
"data": {
"id": "idstring",
"name": "nameString",
"address": "addressString",
...
}
}
Where "data" in this case would be a "Client" definition for us. Is there a way to define the 200 OK response
schema and the definitions in the swagger.json file so that AutoRest would map this "data" to a Client class?
In fact the answer is quite trivial, all I had to do is to write the "responses" object of the swagger file like this:
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/Client"
}
}
}
}
}
Besides creating the Client definition. AutoRest generates code that retrieves the "data" object, giving access to the Client within.
Related
I tried to separated swagger spec to smaller files because my NodeJS have too many APIs.
If I write all document to 1 file, it will very large.
So I want to break the swagger spec to smaller files.
let see my code above, root file and separated file in the same folder. When I access to apidoc, it show an error:
Resolver error at paths./login.$ref Could not resolve reference: Tried to resolve a relative URL, without having a basePath. path: 'login.json' basePath: 'undefined'
Example
My root swagger spec:
{
"openapi": "3.0.3",
"info": {
"title": "Swagger Petstore - OpenAPI 3.0",
"description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\n_If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"email": "apiteam#swagger.io"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.0.11"
},
"paths": {
"/login": {
"$ref": "login.json#/paths/~1login"
}
}
}
My separated spec:
{
"openapi": "3.0.3",
"info": {
"title": "Swagger Petstore - OpenAPI 3.0",
"description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [https://swagger.io](https://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\n_If you're looking for the Swagger 2.0/OAS 2.0 version of Petstore, then click [here](https://editor.swagger.io/?url=https://petstore.swagger.io/v2/swagger.yaml). Alternatively, you can load via the `Edit > Load Petstore OAS 2.0` menu option!_\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"email": "apiteam#swagger.io"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.0.11"
},
"paths": {
"/login": {
"post": {
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
The API I'm trying to describe has a structure where the root object can contain an arbitrary number of child objects (properties that are themselves objects). The "key", or property in the root object, is the unique identifier of the child object, and the value is the rest of the child object's data.
{
"child1": { ... bunch of stuff ... },
"child2": { ... bunch of stuff ... },
...
}
This could similarly be modeled as an array, e.g.:
[
{ "id": "child1", ... bunch of stuff ... },
{ "id": "child2", ... bunch of stuff ... },
...
]
but this both makes it structurally less clear what the identifying property is and makes uniqueness among the children's ID implicit rather than explicit, so we want to use an object, or a map.
I've seen the Swagger documentation for Model with Map/Dictionary Properties, but that doesn't adequately suit my use case. Writing something like:
"Parent": {
"additionalProperties": {
"$ref": "#/components/schemas/Child",
}
Yields something like this:
This adequately communicates the descriptiveness of the value in the property, but how do I document what the restrictions are for the "key" in the object? Ideally I'd like to say something like "it's not just any arbitrary string, it's the ID that corresponds to the child". Is this supported in any way?
Your example is correct.
how do I document what the restrictions are for the "key" in the object? Ideally I'd like to say something like "it's not just any arbitrary string, it's the ID that corresponds to the child". Is this supported in any way?
OpenAPI 3.1
OAS 3.1 fully supports JSON Schema 2020-12, including patternProperties. This keyword lets you define the format of dictionary keys by using a regular expression:
"Parent": {
"type": "object",
"patternProperties": {
"^child\d+$": {
"$ref": "#/components/schemas/Child"
}
},
"description": "A map of `Child` schemas, where the keys are IDs that correspond to the child"
}
Or, if the property names are defined by an enum, you can use propertyNames to define that enum:
"Parent": {
"type": "object",
"propertyNames": {
"enum": ["foo", "bar"]
},
"additionalProperties": {
"$ref": "#/components/schemas/Child"
}
}
OpenAPI 3.0 and 2.0
Dictionary keys are assumed to be strings, but there's no way to limit the contents/format of keys. You can document any restrictions and specifics verbally in the schema description. Adding schema examples could help illustrate what your dictionary/map might look like.
"Parent": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/Child"
},
"description": "A map of `Child` schemas, where the keys are IDs that correspond to the child",
"example": {
"child1": { ... bunch of stuff ... },
"child2": { ... bunch of stuff ... },
}
If the possible key names are known (for example, they are part of an enum), you can define your dictionary as a regular object and the keys as individual object properties:
// Keys can be: key1, key2, key3
"Parent": {
"type": "object",
"properties": {
"key1": { "$ref": "#/components/schemas/Child" },
"key2": { "$ref": "#/components/schemas/Child" },
"key3": { "$ref": "#/components/schemas/Child" }
}
}
Then you can add "additionalProperties": false to really ensure that only those keys are used.
So maybe I'm trying to go into too much detail in my descriptor, but here's my use case. While defining the schema of the object that is returned in the response body for my API, I have one property of the object the value of which is an object with variable properties, so I am using the additionalProperties descriptor.
{
"type": "object",
"additionalProperties": {
"type": "string"
}
}
However instead of describing the type of the values in this variable keyed object as string, I would like to describe them more precisely, seeing that the string is actually a pipe delimited serialization of an array. Example:
{
"property1": {
"variableProperty1": "info1|info2|info3",
"variableProperty2": "info1|info2|info3"
}
}
Is there any way of describing this pipe-delimited serialization? Something like:
{
"type": "object",
"additionalProperties": {
"type": "array",
"explode": false,
"encoding": {
"style": "pipeDelimited"
}
},
}
Or is this only possible for query parameters?
I am using Swashbuckle with Swagger UI in a .Net project. I am using the following attribute on a controller.
[SwaggerResponse(HttpStatusCode.OK, "IEnumerable<EmployeeModel>", typeof(IEnumerable<EmployeeModel>))]
The generated JSON doc produces this:
"responses": {
"200": {
"description": "IEnumerable<EmployeeModel>",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/ResourceModels.EmployeeModel"
}
}
},
"400": {
"description": "BadRequest"
}
}
Swagger UI however only displays IEnumerable and drops the <EmployeeModel>. I am sure the carets are the culprit. Is there a workaround for this?
According to Swagger:
That's actually a bug in the description. That field is gfm, meaning anything in <> will be treated as html, so if you want those characters to appear you need to escape them.
I have a simple JSON object that can contain key/values for which the exact values are not known upfront. They depend on some server side process. How do I model this in Swagger?
An example of the JSON would be:
...
,message: "invalid length. Must be in between {min} and {max}"
,attributes: {
min: 0
,max: 6
}
...
Another example would be:
...
,message: "You must fill out this field as well because {field} has a value"
,attributes: {
field: "age"
}
...
The following solution will only work with Swagger 2.0.
Define the model as described like this:
{
"type": "object",
"properties": {
"message": {
"type": "string"
},
"attributes": {
"type": "object",
"additionalProperties": {}
}
}
}
This describes attributes as a map of properties, where the value can be anything (string, number, array and even an object).