Swagger
Sangeeta Gulia
Software Consultant
Knoldus Software LLP
AGENDA
➔
What’s Swagger?
➔
Why Swagger?
➔
Swagger Components
➔
Data Types
➔
Generating Swagger Spec
➔
Getting started with Play-Swagger
➔
Important Attributes
➔
Swagger Codegen
➔
Generating SDKs
What’s Swagger?
● The goal of Swagger is to define a standard, language-agnostic interface to
REST APIs which allows both humans and computers to discover and
understand the capabilities of the service without access to source code,
documentation.
● When properly defined via Swagger, a consumer can understand and interact
with the remote service with a minimal amount of implementation logic.
● It can be visualised similar to what interfaces have done for lower-level
programming
● Swagger removes the guesswork in calling the service.
Why Swagger?
Swagger is one of the most popular specifications for REST APIs for a number
of reasons:
1.Swagger generates an interactive API console for people to quickly learn
about and try the API.
2.Swagger generates the client SDK code needed for implementations on
various platforms.
3.The Swagger file can be auto-generated from code annotations or using
case class definitions on a lot of different platforms.
4.Swagger has a strong community with helpful contributors.
Swagger Components
● Swagger spec: The Swagger spec is the official schema about name and
element nesting, order, and so on. If you plan on hand-coding the Swagger
files, you’ll need to be extremely familiar with the Swagger spec.
● Swagger editor: The Swagger Editor is an online editor that validates your
YML-formatted content against the rules of the Swagger spec. YML is a syntax
that depends on spaces and nesting. You’ll need to be familiar with YML
syntax and the rules of the Swagger spec to be successful here. The Swagger
editor will flag errors and give you formatting tips. (Note that the Swagger spec
file can be in either JSON or YAML format.)
Example: http://editor.swagger.io/#/
Swagger Components(cont...)
● Swagger-UI: The Swagger UI is an HTML/CSS/JS framework that parses a
JSON or YML file that follows the Swagger spec and generates a navigable UI
of the documentation.
● Swagger-codegen: This utility generates client SDK code for a lot of different
platforms (such as Java, JavaScript, Scala, Python, PHP, Ruby, Scala, and
more). This client code helps developers integrate your API on a specific
platform and provides for more robust implementations that might include
more scaling, threading, and other necessary code. An SDK is supportive
tooling that helps developers use the REST API.
Data Types
Note: Primitives have an optional modifier property format.
Generating Swagger Spec
● Two Techniques:
1) Using Annotations
2) Using iheart’s play-swagger
(A library that generates swagger specs from route files and case class
reflection, no code annotation needed.)
Getting started with play-swagger
● Step – 1 : Add dependency to build.sbt.
libraryDependencies += "com.iheart" %% "play-swagger" % "0.4.0"
● Step – 2 : Add a base swagger.yml (or swagger.json) to the resources (for
example, conf folder in the play application).
This one needs to provide all the required fields according to swagger spec.
Getting started with play-swagger (cont...)
Basic swagger.json
{
"swagger": "2.0",
"host": "localhost:9000",
"consumes": [
"application/json",
"application/text"
],
"produces": [
"application/json"
]
}
Getting started with play-swagger (cont..)
● Step – 3 : You can use swagger-ui webjar and have your play app serving the
swagger ui:
Add the following dependency:
libraryDependencies += "org.webjars" % "swagger-ui" % "2.1.4"
● Step – 4 : Add the following to your routes file:
### NoDocs ###
GET /swagger.json controllers.ApiSpecs.specs
### NoDocs ###
GET /docs/*file controllers.Assets.versioned(path:String=
"/public/lib/swagger-ui", file:String)
Getting started with play-swagger (cont..)
● Step – 5 : Now we need to create the controller(ApiSpecs as mentioned in
routes) who will be responsible for generating spec file, reading required things
from routes file and models(i.e case classes).
--------------------------------------------------------------------------------------------------------
ApiSpecs.scala
--------------------------------------------------------------------------------------------------------
import play.api.libs.concurrent.Execution.Implicits._
import com.iheart.playSwagger.SwaggerSpecGenerator
import play.api.mvc.{Action, Controller}
import scala.concurrent.Future
class ApiSpecs extends Controller {
implicit val cl = getClass.getClassLoader
val domainPackage = "models"
private lazy val generator = SwaggerSpecGenerator(domainPackage)
def specs = Action.async { _ =>
Future.fromTry(generator.generate()).map(Ok(_))
}
}
Getting started with play-swagger (cont..)
● SwaggerSpecGenerator is a case class which takes DomainModelQualifier,
which in turn accepts namespace*.
● Generate is the method which takes location of route file as argument.
(Note: if not specified, by default it uses conf/routes)
● Now you can see the generated swagger UI at :
http://localhost:9000/docs/index.html?url=/swagger.json#/
Important Attributes
S. No. Attribute Name Description
1 tags Used to group multiple routes.
2 summary Describe short summary about route.
3 consumes Determine the type of data being accepted by any route.
4 produces Determine the type of data being returned as response.
5 parameters Define the parameters(including attributes type, format, required,
description, in). It hold array of parameters.
6 responses Define the schema of responses as per different response codes
7 schema Define schema of response
8 description Used to provide description for a route, any parameter or any
response.
9 required Used to denote if a parameter is required or not. (default: false)
How to hide an endpoint?
If you don't want an end point to be included, add ### NoDocs ### in front of it
e.g.
### NoDocs ###
GET /docs/swagger-ui/*file
controllers.Assets.at(path:String="/public/lib/swagger-ui", file:String)
Specify parameters in query
###
# {
# "tags" : ["QueryStringContainData"],
# "summary" : "get student record(query example)",
# "parameters" : [ {
# "in" : "query",
# "name":"id",
# "description": "Student Id",
# "required":true,
# "type":"string"
# } ],
# "responses": {
# "200": {
# "description": "success",
# "schema": { "$ref": "#/definitions/models.StudentRecordResponse" }
# }
# }
# }
###
GET /get/student/record/
controllers.SwaggerUiController.getStudentRecordById
Specify parameters in path
###
# {
# "tags" : ["PathContainData"],
# "summary" : "get student record(path example)",
# "parameters" : [ {
# "in" : "path",
# "name":"id",
# "description": "Student Id",
# "required":true,
# "type":"string"
# } ],
# "responses": {
# "200": {
# "description": "success",
# "schema": { "$ref": "#/definitions/models.StudentRecordResponse" }
# }
# }
# }
###
GET /student/record/:id
controllers.SwaggerUiController.getRecordById(id: Int)
Specify parameters as formUrlEncodedBody
###
● # {
● # "tags" : ["BodyData"],
● # "summary" : "mirror response",
● # "consumes" : [ "application/x-www-form-urlencoded" ],
● # "parameters" : [ {
● # "in" : "formData",
● # "name":"id",
● # "description": "Employee Id",
● # "required":true,
● # "type":"integer",
● # "format":"int64"
● # } ],
● # "responses": {
● # "200": {
● # "description": "success",
● # "schema": { "$ref": "#/definitions/models.RequestWithBody" }
● # }
● # }
● # }
● ###
Sending Multipart form data
###
# {
# "tags" : ["Multipart Data"],
# "summary" : "multipart data",
# "consumes" : [ "multipart/form-data" ],
# "parameters" : [
# {
# "in" : "formData",
# "name":"key",
# "required":true,
# "type":"string"
# },
# ],
# "responses": {
# "200": {
# "description": "success",
# "schema": {
# "$ref": "#/definitions/models.swagger.Response"
# }
# }
# }
# }
###
Specify response definition in Swagger.json
“definitions”: {
"InternRecordResponse" : {
"type":"object",
"required":[ "data" ],
"properties": {
"data" : {
"$ref": "#/definitions/InternRecord"
}
}
},
"InternRecord": {
"type":"object",
"properties": {
"intern_id" : { "type": "string" },
"intern_email" : { "type": "string" }
}
}
}
USAGE:
"$ref": "#/definitions/InternRecordResponse"
Specify response details
# "responses": {
# "200": {
# "description": "success",
# "schema": {
# "$ref": "#/definitions/models.RequestWithBody"
# }
# },
# "400": {
# "description": "Problem in parsing input json data",
# "schema": {
# "$ref": "#/definitions/models.ErrorResponse"
# }
# },
# "default": {
# "description": "error",
# "schema": {
# "$ref": "#/definitions/models.ErrorResponse"
# }
# }
# }
Handling Option field on UI
We can have optional field, but on UI it can be identified under Model tab and not
in model schema.
This feature is yet to be included.
Swagger Codegen
swagger-codegen contains a template-driven engine to generate
documentation, API clients and server stubs in different languages by parsing
your OpenAPI / Swagger definition.
Generating SDKs
git clone https://github.com/swagger-api/swagger-codegen
cd swagger-codegen
mvn clean package
Command to create SDK:
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar
generate 
-i http://petstore.swagger.io/v2/swagger.json 
-l php 
-o /var/tmp/php_api_client
Demo
Demo project can be found at :
https://github.com/knoldus/swagger-demo
Thank You...
➔
https://github.com/iheartradio/play-swagger
➔
https://github.com/swagger-api/swagger-codegen
References

Introduction to Swagger

  • 1.
  • 2.
    AGENDA ➔ What’s Swagger? ➔ Why Swagger? ➔ SwaggerComponents ➔ Data Types ➔ Generating Swagger Spec ➔ Getting started with Play-Swagger ➔ Important Attributes ➔ Swagger Codegen ➔ Generating SDKs
  • 3.
    What’s Swagger? ● Thegoal of Swagger is to define a standard, language-agnostic interface to REST APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation. ● When properly defined via Swagger, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. ● It can be visualised similar to what interfaces have done for lower-level programming ● Swagger removes the guesswork in calling the service.
  • 4.
    Why Swagger? Swagger isone of the most popular specifications for REST APIs for a number of reasons: 1.Swagger generates an interactive API console for people to quickly learn about and try the API. 2.Swagger generates the client SDK code needed for implementations on various platforms. 3.The Swagger file can be auto-generated from code annotations or using case class definitions on a lot of different platforms. 4.Swagger has a strong community with helpful contributors.
  • 5.
    Swagger Components ● Swaggerspec: The Swagger spec is the official schema about name and element nesting, order, and so on. If you plan on hand-coding the Swagger files, you’ll need to be extremely familiar with the Swagger spec. ● Swagger editor: The Swagger Editor is an online editor that validates your YML-formatted content against the rules of the Swagger spec. YML is a syntax that depends on spaces and nesting. You’ll need to be familiar with YML syntax and the rules of the Swagger spec to be successful here. The Swagger editor will flag errors and give you formatting tips. (Note that the Swagger spec file can be in either JSON or YAML format.) Example: http://editor.swagger.io/#/
  • 6.
    Swagger Components(cont...) ● Swagger-UI:The Swagger UI is an HTML/CSS/JS framework that parses a JSON or YML file that follows the Swagger spec and generates a navigable UI of the documentation. ● Swagger-codegen: This utility generates client SDK code for a lot of different platforms (such as Java, JavaScript, Scala, Python, PHP, Ruby, Scala, and more). This client code helps developers integrate your API on a specific platform and provides for more robust implementations that might include more scaling, threading, and other necessary code. An SDK is supportive tooling that helps developers use the REST API.
  • 7.
    Data Types Note: Primitiveshave an optional modifier property format.
  • 8.
    Generating Swagger Spec ●Two Techniques: 1) Using Annotations 2) Using iheart’s play-swagger (A library that generates swagger specs from route files and case class reflection, no code annotation needed.)
  • 9.
    Getting started withplay-swagger ● Step – 1 : Add dependency to build.sbt. libraryDependencies += "com.iheart" %% "play-swagger" % "0.4.0" ● Step – 2 : Add a base swagger.yml (or swagger.json) to the resources (for example, conf folder in the play application). This one needs to provide all the required fields according to swagger spec.
  • 10.
    Getting started withplay-swagger (cont...) Basic swagger.json { "swagger": "2.0", "host": "localhost:9000", "consumes": [ "application/json", "application/text" ], "produces": [ "application/json" ] }
  • 11.
    Getting started withplay-swagger (cont..) ● Step – 3 : You can use swagger-ui webjar and have your play app serving the swagger ui: Add the following dependency: libraryDependencies += "org.webjars" % "swagger-ui" % "2.1.4" ● Step – 4 : Add the following to your routes file: ### NoDocs ### GET /swagger.json controllers.ApiSpecs.specs ### NoDocs ### GET /docs/*file controllers.Assets.versioned(path:String= "/public/lib/swagger-ui", file:String)
  • 12.
    Getting started withplay-swagger (cont..) ● Step – 5 : Now we need to create the controller(ApiSpecs as mentioned in routes) who will be responsible for generating spec file, reading required things from routes file and models(i.e case classes). -------------------------------------------------------------------------------------------------------- ApiSpecs.scala -------------------------------------------------------------------------------------------------------- import play.api.libs.concurrent.Execution.Implicits._ import com.iheart.playSwagger.SwaggerSpecGenerator import play.api.mvc.{Action, Controller} import scala.concurrent.Future class ApiSpecs extends Controller { implicit val cl = getClass.getClassLoader val domainPackage = "models" private lazy val generator = SwaggerSpecGenerator(domainPackage) def specs = Action.async { _ => Future.fromTry(generator.generate()).map(Ok(_)) } }
  • 13.
    Getting started withplay-swagger (cont..) ● SwaggerSpecGenerator is a case class which takes DomainModelQualifier, which in turn accepts namespace*. ● Generate is the method which takes location of route file as argument. (Note: if not specified, by default it uses conf/routes) ● Now you can see the generated swagger UI at : http://localhost:9000/docs/index.html?url=/swagger.json#/
  • 14.
    Important Attributes S. No.Attribute Name Description 1 tags Used to group multiple routes. 2 summary Describe short summary about route. 3 consumes Determine the type of data being accepted by any route. 4 produces Determine the type of data being returned as response. 5 parameters Define the parameters(including attributes type, format, required, description, in). It hold array of parameters. 6 responses Define the schema of responses as per different response codes 7 schema Define schema of response 8 description Used to provide description for a route, any parameter or any response. 9 required Used to denote if a parameter is required or not. (default: false)
  • 15.
    How to hidean endpoint? If you don't want an end point to be included, add ### NoDocs ### in front of it e.g. ### NoDocs ### GET /docs/swagger-ui/*file controllers.Assets.at(path:String="/public/lib/swagger-ui", file:String)
  • 16.
    Specify parameters inquery ### # { # "tags" : ["QueryStringContainData"], # "summary" : "get student record(query example)", # "parameters" : [ { # "in" : "query", # "name":"id", # "description": "Student Id", # "required":true, # "type":"string" # } ], # "responses": { # "200": { # "description": "success", # "schema": { "$ref": "#/definitions/models.StudentRecordResponse" } # } # } # } ### GET /get/student/record/ controllers.SwaggerUiController.getStudentRecordById
  • 17.
    Specify parameters inpath ### # { # "tags" : ["PathContainData"], # "summary" : "get student record(path example)", # "parameters" : [ { # "in" : "path", # "name":"id", # "description": "Student Id", # "required":true, # "type":"string" # } ], # "responses": { # "200": { # "description": "success", # "schema": { "$ref": "#/definitions/models.StudentRecordResponse" } # } # } # } ### GET /student/record/:id controllers.SwaggerUiController.getRecordById(id: Int)
  • 18.
    Specify parameters asformUrlEncodedBody ### ● # { ● # "tags" : ["BodyData"], ● # "summary" : "mirror response", ● # "consumes" : [ "application/x-www-form-urlencoded" ], ● # "parameters" : [ { ● # "in" : "formData", ● # "name":"id", ● # "description": "Employee Id", ● # "required":true, ● # "type":"integer", ● # "format":"int64" ● # } ], ● # "responses": { ● # "200": { ● # "description": "success", ● # "schema": { "$ref": "#/definitions/models.RequestWithBody" } ● # } ● # } ● # } ● ###
  • 19.
    Sending Multipart formdata ### # { # "tags" : ["Multipart Data"], # "summary" : "multipart data", # "consumes" : [ "multipart/form-data" ], # "parameters" : [ # { # "in" : "formData", # "name":"key", # "required":true, # "type":"string" # }, # ], # "responses": { # "200": { # "description": "success", # "schema": { # "$ref": "#/definitions/models.swagger.Response" # } # } # } # } ###
  • 20.
    Specify response definitionin Swagger.json “definitions”: { "InternRecordResponse" : { "type":"object", "required":[ "data" ], "properties": { "data" : { "$ref": "#/definitions/InternRecord" } } }, "InternRecord": { "type":"object", "properties": { "intern_id" : { "type": "string" }, "intern_email" : { "type": "string" } } } } USAGE: "$ref": "#/definitions/InternRecordResponse"
  • 21.
    Specify response details #"responses": { # "200": { # "description": "success", # "schema": { # "$ref": "#/definitions/models.RequestWithBody" # } # }, # "400": { # "description": "Problem in parsing input json data", # "schema": { # "$ref": "#/definitions/models.ErrorResponse" # } # }, # "default": { # "description": "error", # "schema": { # "$ref": "#/definitions/models.ErrorResponse" # } # } # }
  • 22.
    Handling Option fieldon UI We can have optional field, but on UI it can be identified under Model tab and not in model schema. This feature is yet to be included.
  • 23.
    Swagger Codegen swagger-codegen containsa template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
  • 24.
    Generating SDKs git clonehttps://github.com/swagger-api/swagger-codegen cd swagger-codegen mvn clean package Command to create SDK: java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i http://petstore.swagger.io/v2/swagger.json -l php -o /var/tmp/php_api_client
  • 25.
    Demo Demo project canbe found at : https://github.com/knoldus/swagger-demo
  • 27.
  • 28.