Swagger 2.0 - Inconsistent Results From Swagger Source - swagger

Swagger source below. When I run the swagger-tools validator, I receive no errors. When I load this in the editor, I see output but it is incorrect - it shows wrong types, and an incomplete Member object. When I try to use the code generator cli java tool, I get the following errors:
711 [main] ERROR io.swagger.models.properties.PropertyBuilder - no property for null, null
712 [main] WARN io.swagger.util.PropertyDeserializer - no property from null, null, {ENUM=null, TITLE=null, DESCRIPTION=null, DEFAULT=null, PATTERN=null, DESCRIMINATOR=null, MIN_ITEMS=null, MAX_ITEMS=null, MIN_PROPERTIES=null, MAX_PROPERTIES=null, MIN_LENGTH=null, MAX_LENGTH=null, MINIMUM=null, MAXIMUM=null, EXCLUSIVE_MINIMUM=null, EXCLUSIVE_MAXIMUM=null, UNIQUE_ITEMS=null, EXAMPLE=null, TYPE=null, FORMAT=null}
822 [main] ERROR io.swagger.codegen.DefaultCodegen - unexpected missing property for name null
822 [main] WARN io.swagger.codegen.DefaultCodegen - skipping invalid property {
"type" : "array"
}
{
"swagger": "2.0",
"info": {
"title": "V1 Inmar CRM API",
"description": "CRM API",
"version": "1.0.0"
},
"produces": ["application/json"],
"basePath": "/v1",
"paths": {
"/member": {
"get": {
"x-swagger-router-controller": "member",
"tags": ["member"],
"operationId": "GetMember",
"parameters": [
{ "$ref": "#/parameters/x-inmar-rest-api-key" },
{ "$ref": "#/parameters/x-inmar-memberID" }
],
"responses": {
"200": {
"description": "success",
"schema": { "$ref": "#/definitions/Member" }
}
}
},
"post": {
"x-swagger-route-controller": "member",
"tags": ["member"],
"operationId": "PostMember",
"parameters": [
{ "$ref": "#/parameters/x-inmar-rest-api-key" },
{ "$ref": "#/parameters/x-inmar-memberID" },
{ "$ref": "#/parameters/member" }
],
"responses": {
"200": { "$ref": "#/responses/generic-200" }
}
}
}
},
"parameters": {
"x-inmar-rest-api-key": {
"name": "X-Inmar-REST-API-Key",
"description": "API Access Key.",
"in": "header",
"required": true,
"type": "string"
},
"x-inmar-memberID": {
"name": "X-Inmar-MemberID",
"description": "Unique ID for member.",
"in": "header",
"required": true,
"type": "string"
},
"member": {
"description": "member object",
"in": "body",
"name": "body",
"required": true,
"schema": {
"$ref": "#/definitions/Member"
}
}
},
"responses": {
"generic-200": {
"description": "Success"
}
},
"definitions": {
"Member": {
"description": "member",
"type": "object",
"properties": {
"active": {
"type": "boolean",
"default": true
},
"identity": {
"type": "object",
"required": [
"user_id"
],
"properties": {
"user_id": {
"type": "string",
"maxLength": 50,
"format": "email"
},
"password": {
"type": "string",
"minLength": 8,
"maxLength": 20
},
"proxy_id": {
"type": "integer"
}
}
},
"pii": {
"type": "object",
"description": "personally_identifiable_information.",
"properties": {
"alt_email": {
"type": "string",
"description": "Secondary email addresses that may or may not match the id.",
"format": "email"
},
"first_name": {
"type": "string",
"minLength": 1,
"maxLength": 25
},
"last_name": {
"type": "string",
"minLength": 1,
"maxLength": 25
},
"primary_address_one": {
"type": "string",
"minLength": 1,
"maxLength": 47
},
"primary_address_two": {
"type": "string",
"minLength": 1,
"maxLength": 47
},
"primary_address_city": {
"type": "string",
"minLength": 1,
"maxLength": 47
},
"primary_address_state": {
"type": "string",
"minLength": 2,
"maxLength": 2,
"description": "US states and US territories and Canadian provinces.",
"enum": [
"AA",
"AB",
"AE",
"AK",
"AL",
"AP",
"AR",
"AS",
"AZ",
"BC",
"CA",
"CO",
"CT",
"DC",
"DE",
"FL",
"FM",
"GA",
"GU",
"HI",
"IA",
"ID",
"IL",
"IN",
"KS",
"KY",
"LA",
"MA",
"MB",
"MD",
"ME",
"MH",
"MI",
"MN",
"MO",
"MP",
"MS",
"MT",
"NB",
"NC",
"ND",
"NE",
"NH",
"NJ",
"NL",
"NM",
"NS",
"NT",
"NU",
"NV",
"NY",
"OH",
"OK",
"ON",
"OR",
"PA",
"PE",
"PR",
"PW",
"QC",
"RI",
"SC",
"SD",
"SK",
"TN",
"TX",
"UK",
"UT",
"VA",
"VI",
"VT",
"WA",
"WI",
"WV",
"WY",
"YT"
]
},
"primary_address_postal_code": {
"type": "string",
"minLength": 5,
"maxLength": 10
},
"primary_address_country": {
"type": "string",
"enum": [
"US",
"CA"
]
},
"birthdate": {
"type": "string"
},
"language_preference": {
"type": "string"
},
"gender": {
"type": "string",
"enum": [
"male",
"female"
]
}
}
},
"profiles": {
"type": "array",
"items": {
"properties": {
"site_id": {
"type": "integer"
},
"survey_data": {
"type": "object",
"required": [
"survey_id",
"survey_responses"
],
"properties": {
"survey_id": {
"type": "integer",
"description": "Unique identifier of a profile survey."
},
"survey_responses": {
"type": "array",
"items": {
"required": [
"question_id",
"response_id",
"free_form_value"
],
"properties": {
"question_id": {
"type": "integer",
"description": "Unique identifier of a profile survey question."
},
"response_id": {
"type": "integer",
"description": "Unique identifier of a profile question response.",
"default": 0
},
"free_form_value": {
"type": "string",
"description": "Consumer free form response",
"default": ""
}
}
}
}
}
}
}
}
},
"optins": {
"type": "array",
"items": {
"$ref": "#/definitions/OptIn"
}
}
}
},
"OptIn": {
"description": "survey response",
"type": "object",
"properties":{
"optin_id": {
"type": "integer",
"description": "Unique identifier of an opt in question/choice. e.g. newsletter"
},
"optin_value": {
"type": "integer",
"enum": [ 0, 1 ],
"description": "Optin Response of 0=Optout and 1=Optin"
}
},
"required": [
"optin_id",
"optin_value"
]
}
}
}

Related

OpenAPI v3, how to hide objects in "Schemas" section

I'm using OpenAPI v3 to create my API docs and having them hosted on app.swaggerhub.com
Is there a way to hide an item from showing up in the Schemas section at the bottom? The real API has dozens of Schema objects, so it'd be very helpful to hide some of them.
Example:
Running this on https://editor-next.swagger.io/
{
"openapi": "3.0.3",
"info": {
"title": "Swagger Petstore - OpenAPI 3.0",
"description": "example",
"version": "1.0.11"
},
"servers": [
{
"url": "https://petstore3.swagger.io/api/v3"
}
],
"paths": {
"/pet": {
"post": {
"summary": "Add a new pet to the store",
"description": "Add a new pet to the store",
"operationId": "addPet",
"requestBody": {
"description": "Create a new pet in the store",
"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"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Successful operation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Order": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"example": 10
},
"petId": {
"type": "integer",
"format": "int64",
"example": 198772
},
"quantity": {
"type": "integer",
"format": "int32",
"example": 7
},
"shipDate": {
"type": "string",
"format": "date-time"
},
"status": {
"type": "string",
"description": "Order Status",
"example": "approved",
"enum": [
"placed",
"approved",
"delivered"
]
},
"complete": {
"type": "boolean"
}
},
"xml": {
"name": "order"
}
},
"Customer": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"example": 100000
},
"username": {
"type": "string",
"example": "fehguy"
},
"address": {
"type": "array",
"xml": {
"name": "addresses",
"wrapped": true
},
"items": {
"$ref": "#/components/schemas/Address"
}
}
},
"xml": {
"name": "customer"
}
},
"Address": {
"type": "object",
"properties": {
"street": {
"type": "string",
"example": "437 Lytton"
},
"city": {
"type": "string",
"example": "Palo Alto"
},
"state": {
"type": "string",
"example": "CA"
},
"zip": {
"type": "string",
"example": "94301"
}
},
"xml": {
"name": "address"
}
},
"Category": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"example": 1
},
"name": {
"type": "string",
"example": "Dogs"
}
},
"xml": {
"name": "category"
}
},
"User": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"example": 10
},
"username": {
"type": "string",
"example": "theUser"
},
"firstName": {
"type": "string",
"example": "John"
},
"lastName": {
"type": "string",
"example": "James"
},
"email": {
"type": "string",
"example": "john#email.com"
},
"password": {
"type": "string",
"example": "12345"
},
"phone": {
"type": "string",
"example": "12345"
},
"userStatus": {
"type": "integer",
"description": "User Status",
"format": "int32",
"example": 1
}
},
"xml": {
"name": "user"
}
},
"Tag": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
}
},
"xml": {
"name": "tag"
}
},
"Pet": {
"required": [
"name",
"photoUrls"
],
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"example": 10
},
"name": {
"type": "string",
"example": "doggie"
},
"category": {
"$ref": "#/components/schemas/Category"
},
"photoUrls": {
"type": "array",
"xml": {
"wrapped": true
},
"items": {
"type": "string",
"xml": {
"name": "photoUrl"
}
}
},
"tags": {
"type": "array",
"xml": {
"wrapped": true
},
"items": {
"$ref": "#/components/schemas/Tag"
}
},
"status": {
"type": "string",
"description": "pet status in the store",
"enum": [
"available",
"pending",
"sold"
]
}
},
"xml": {
"name": "pet"
}
},
"ApiResponse": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"type": {
"type": "string"
},
"message": {
"type": "string"
}
},
"xml": {
"name": "##default"
}
}
},
"requestBodies": {
"Pet": {
"description": "Pet object that needs to be added to the store",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"UserArray": {
"description": "List of user object",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
},
"securitySchemes": {
"petstore_auth": {
"type": "oauth2",
"flows": {
"implicit": {
"authorizationUrl": "https://petstore3.swagger.io/oauth/authorize",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
}
}
},
"api_key": {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
}
}
}
...this gets generated:
In this example, I'd like to hide a few of the schema items from view (like Customer or Address).
Note: I'm not self-hosting, so I'm hoping there's a tag I can put into the YAML or JSON.
Thanks,
Ryan

Avro multiple enum int the same type (avro.SchemaParseException: Can't redefine)

A have the following avro schema, but if I want to parse it, then I got the following error:
Exception in thread "main" org.apache.avro.SchemaParseException: Can't redefine: ...
{
"name": "card_1_nr",
"type": "string"
}, {
"name": "card_1_type",
"type": {
"name": "card_type",
"type": "enum",
"symbols": ["diamonds", "clubs", "hearts", "spades"],
"default": "diamonds"
}
}, {
"name": "card_2_nr",
"type": "string"
}, {
"name": "card_2_type",
"type": {
"name": "card_type",
"type": "enum",
"symbols": ["diamonds", "clubs", "hearts", "spades"],
"default": "diamonds"
}
}
Just simply need to use the enume type name:
{
"name": "card_1_nr",
"type": "string"
}, {
"name": "card_1_type",
"type": {
"name": "card_type",
"type": "enum",
"symbols": ["diamonds", "clubs", "hearts", "spades"],
"default": "diamonds"
}
}, {
"name": "card_2_nr",
"type": "string"
}, {
"name": "card_2_type",
"type": "card_type"
}

Swagger data validation with allOf and additional properties

Need help to solve a swagger definiton schema using allOf and additionalProperties: false
Here my JSON Schema
"deliveryContact": {
"allOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"maxLength": 1024
},
"phone": {
"type": "string",
"maxLength": 24
}
}
},
{
"$ref": "#/definitions/address"
}
]
},
"address": {
"type": "object",
"additionalProperties": false,
"properties": {
"address": {
"type": "string",
"maxLength": 1024
},
"postalCode": {
"type": "string",
"maxLength": 12
},
"city": {
"type": "string",
"maxLength": 512
},
"state": {
"type": "string",
"maxLength": 512
}
}
},
Sample data
delivery: {
address: 'my address',
postalCode: 'my postalCode',
city: 'my city',
state: 'my state',
name: 'my name',
phone: 'my phone'
},
I use AJV 6.10.0 to validate my data, but I think I have a wrong schema definition.
With Ajv options :
ajv = require('ajv')({
allErrors: true,
verbose: true,
removeAdditional: false,
});
Actually, I have 6 errors which warn of additional properties for each property
During validation of the first object in allOf (name and phone), validation found the error on (address, postalCode, city and state)
If I remove additionalProperties of the first allOf object (name, phone), during validation of address schema, the validation found the error on (name and phone)
How can I solve my schema definition
I managed to make it works, I have update your data structure to be more logical, see below :
JSON Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"delivery"
],
"properties": {
"delivery": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"phone",
"address"
],
"properties": {
"name": {
"type": "string",
"maxLength": 1024
},
"phone": {
"type": "string",
"maxLength": 24
},
"address": {
"$ref": "#/definitions/address"
}
}
}
},
"definitions": {
"address": {
"type": "object",
"additionalProperties": false,
"properties": {
"address": {
"type": "string",
"maxLength": 1024
},
"postalCode": {
"type": "string",
"maxLength": 12
},
"city": {
"type": "string",
"maxLength": 512
},
"state": {
"type": "string",
"maxLength": 512
}
}
}
}
}
Sample data
{
"delivery": {
"address": {
"address": "myaddress",
"postalCode": "mypostalCode",
"city": "mycity",
"state": "mystate"
},
"name": "myname",
"phone": "myphone"
}
}
If you want to test it, you can do that here : https://www.jsonschemavalidator.net/

api-doc generated by Springfox not work with swagger-codegen

I'm testing if I can use the api-doc generated by springfox to generate Java client code through swagger-codegen.
I use the boot-swagger module from springfox-demos and the generated api-doc looks like below (pretty formatted)
{
"swagger": "2.0",
"info": {
"description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
"version": "2.0",
"title": "Springfox petstore API",
"termsOfService": "http://springfox.io",
"contact": {
"name": "springfox"
},
"license": {
"name": "Apache License Version 2.0",
"url": "https://github.com/springfox/springfox/blob/master/LICENSE"
}
},
"host": "localhost:8080",
"basePath": "/springfox",
"tags": [
{
"name": "category-controller",
"description": "Category Controller"
}
],
"paths": {
"/categories{?categories}": {
"post": {
"tags": [
"category-controller"
],
"summary": "map",
"operationId": "mapUsingPOST",
"consumes": [
"application/json"
],
"produces": [
"*/*"
],
"parameters": [
{
"name": "categories",
"in": "query",
"description": "categories",
"required": false,
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "multi"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"type": "string",
"enum": [
"ONE",
"TWO",
"THREE"
]
}
}
},
"201": {
"description": "Created"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
}
}
},
"/category/Resource{?someEnum}": {
"get": {
"tags": [
"category-controller"
],
"summary": "search",
"operationId": "searchUsingGET",
"produces": [
"*/*"
],
"parameters": [
{
"name": "someEnum",
"in": "query",
"description": "someEnum",
"required": true,
"type": "string",
"enum": [
"ONE",
"TWO",
"THREE"
]
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "string"
}
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
}
}
},
"/category/map": {
"get": {
"tags": [
"category-controller"
],
"summary": "map",
"operationId": "mapUsingGET",
"produces": [
"*/*"
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/Pet"
}
}
}
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
}
}
},
"/category/{id}": {
"post": {
"tags": [
"category-controller"
],
"summary": "someOperation",
"operationId": "someOperationUsingPOST",
"consumes": [
"application/json"
],
"produces": [
"*/*"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "id",
"required": true,
"type": "integer",
"format": "int64"
},
{
"in": "body",
"name": "userId",
"description": "userId",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "OK"
},
"201": {
"description": "Created"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
}
}
},
"/category/{id}/map{?test}": {
"post": {
"tags": [
"category-controller"
],
"summary": "map",
"operationId": "mapUsingPOST_1",
"consumes": [
"application/json"
],
"produces": [
"*/*"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "id",
"required": true,
"type": "string"
},
{
"name": "test",
"in": "query",
"description": "test",
"required": true,
"items": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
],
"responses": {
"200": {
"description": "OK"
},
"201": {
"description": "Created"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
}
}
},
"/category/{id}/{userId}": {
"post": {
"tags": [
"category-controller"
],
"summary": "ignoredParam",
"operationId": "ignoredParamUsingPOST",
"consumes": [
"application/json"
],
"produces": [
"*/*"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "id",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"200": {
"description": "OK"
},
"201": {
"description": "Created"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
}
}
}
},
"definitions": {
"Category": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
}
},
"title": "Category"
},
"Map«string,Pet»": {
"type": "object",
"title": "Map«string,Pet»",
"additionalProperties": {
"$ref": "#/definitions/Pet"
}
},
"Pet": {
"type": "object",
"properties": {
"category": {
"$ref": "#/definitions/Category"
},
"id": {
"type": "integer",
"format": "int64"
},
"identifier": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"photoUrls": {
"type": "array",
"items": {
"type": "string"
}
},
"status": {
"type": "string",
"description": "pet status in the store",
"allowEmptyValue": false,
"enum": [
"available",
"pending",
"sold"
]
},
"tags": {
"type": "array",
"items": {
"$ref": "#/definitions/Tag"
}
}
},
"title": "Pet"
},
"Tag": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
}
},
"title": "Tag"
}
}
}
The code generation failed and it looks like the api-doc.json does not even fit for swagger specification.
I pasted the code into swagger editor, and it complains for a lot of errors such as
Semantic error at paths./categories{?categories}
Query strings in paths are not allowed.
Jump to line 18
So is it possible to generate client code from the api-doc.json generated by Springfox?
After reading the document of Springfox Reference Documentation, I have solved this issue!
Format like below is because by default springfox applies RFC 6570
./categories{?categories}
3.2. Configuration explained
An example of this would be two apis: First, http://example.org/findCustomersBy?name=Test to find customers by name. Per RFC 6570, this would be represented as http://example.org/findCustomersBy{?name}. Second, http://example.org/findCustomersBy?zip=76051 to find customers by zip. Per RFC 6570, this would be represented as http://example.org/findCustomersBy{?zip}.
One more issue I didn't mention in the question:
"Map«string,Pet»": { // The generated JSON contains special characters
"type": "object",
"title": "Map«string,Pet»",
"additionalProperties": {
"$ref": "#/definitions/Pet"
}
}
The document clearly mentioned the swagger-codegen situation:
6.8.3. Changing how Generic Types are Named
By default, types with generics will be labeled with '\u00ab'(<<), '\u00bb'(>>), and commas. This can be problematic with things like swagger-codegen. You can override this behavior by implementing your own GenericTypeNamingStrategy. For example, if you wanted List to be encoded as 'ListOfString' and Map to be encoded as 'MapOfStringAndObject' you could set the forCodeGeneration customization option to true during plugin customization:
docket.forCodeGeneration(true|false);
To summary, when we generate the docket in springfox for swagger-codegen, we need to specify the following switches:
new Docket(DocumentationType.SWAGGER_2)
.forCodeGeneration(true)
.enableUrlTemplating(false)

Load HTML into Swagger Docs Implementation Notes

I'm attempting to display HTML for my implementation notes for a given endpoint using Swagger Docs. Below, I've typed out the HTML as a string, but I love to load these in as a module of some sort, so that I can simply edit HTML files separately.
I couldn't find an answer in the Google Group and I'd like to see if this is something that is already solved before I create some sort of grunt plug-in to handle it.
Here's my current code:
module.exports = function (swagger) {
var docs = swagger.createResource("/docs/endpoint");
docs.get('/endpoint', "Endpoint Title", {
"summary": "Some description about the endpoint",
"notes": " \
<h2>Getting Started with Endpoint:</h2> \
<br /><p>This endpoint some some really important things.</p> \
",
"type": "",
"nickname": "",
"parameters": [
{
"name": "apiKey",
"description": "The API Key for the requesting application",
"required": true,
"type": "string",
"paramType":"query"
}]
[...]
Is there a cleaner way to implement this?
Swagger 2.0 adds some more flexibility with rich documentation.
One way, is the ability to add markdown tags (GFM flavor) to the description fields.
Another way, is to use the externalDocs property where applicable to add an external documentation resource. An example for it would be:
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService": "http://helloreverb.com/terms/",
"contact": {
"name": "Wordnik API Team",
"email": "foo#example.com",
"url": "http://madskristensen.net"
},
"license": {
"name": "MIT",
"url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT"
}
},
"externalDocs": {
"description": "find more info here",
"url": "https://helloreverb.com/about"
},
"host": "petstore.swagger.wordnik.com",
"basePath": "/api",
"schemes": [
"http"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/pets": {
"get": {
"description": "Returns all pets from the system that the user has access to",
"operationId": "findPets",
"externalDocs": {
"description": "find more info here",
"url": "https://helloreverb.com/about"
},
"produces": [
"application/json",
"application/xml",
"text/xml",
"text/html"
],
"parameters": [
{
"name": "tags",
"in": "query",
"description": "tags to filter by",
"required": false,
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv"
},
{
"name": "limit",
"in": "query",
"description": "maximum number of results to return",
"required": false,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "pet response",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/pet"
}
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/errorModel"
}
}
}
},
"post": {
"description": "Creates a new pet in the store. Duplicates are allowed",
"operationId": "addPet",
"produces": [
"application/json"
],
"parameters": [
{
"name": "pet",
"in": "body",
"description": "Pet to add to the store",
"required": true,
"schema": {
"$ref": "#/definitions/newPet"
}
}
],
"responses": {
"200": {
"description": "pet response",
"schema": {
"$ref": "#/definitions/pet"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/errorModel"
}
}
}
}
},
"/pets/{id}": {
"get": {
"description": "Returns a user based on a single ID, if the user does not have access to the pet",
"operationId": "findPetById",
"produces": [
"application/json",
"application/xml",
"text/xml",
"text/html"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of pet to fetch",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"200": {
"description": "pet response",
"schema": {
"$ref": "#/definitions/pet"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/errorModel"
}
}
}
},
"delete": {
"description": "deletes a single pet based on the ID supplied",
"operationId": "deletePet",
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of pet to delete",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"204": {
"description": "pet deleted"
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/errorModel"
}
}
}
}
}
},
"definitions": {
"pet": {
"required": [
"id",
"name"
],
"externalDocs": {
"description": "find more info here",
"url": "https://helloreverb.com/about"
},
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"newPet": {
"allOf": [
{
"$ref": "pet"
},
{
"required": [
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
}
}
}
]
},
"errorModel": {
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}

Resources