Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/felixbr/swagger-blocks-scala
A library to express swagger specifications using a Scala DSL.
https://github.com/felixbr/swagger-blocks-scala
api-documentation dsl scala swagger
Last synced: 4 days ago
JSON representation
A library to express swagger specifications using a Scala DSL.
- Host: GitHub
- URL: https://github.com/felixbr/swagger-blocks-scala
- Owner: felixbr
- License: mit
- Created: 2016-05-09T20:28:23.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2022-01-31T10:16:12.000Z (about 3 years ago)
- Last Synced: 2024-01-28T04:01:45.851Z (about 1 year ago)
- Topics: api-documentation, dsl, scala, swagger
- Language: Scala
- Homepage:
- Size: 102 KB
- Stars: 7
- Watchers: 2
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# swagger-blocks-scala [![Build Status](https://travis-ci.org/felixbr/swagger-blocks-scala.svg?branch=master)](https://travis-ci.org/felixbr/swagger-blocks-scala)
A library to express swagger specifications using a Scala DSL.
It is inspired mainly by [fotinakis/swagger-blocks](https://github.com/fotinakis/swagger-blocks)
for ruby.Currently this only supports a part of the full swagger-spec.
## Note about current maintenance status
I currently have no personal use for the library anymore, so don't expect frequent updates. Personally I'd recommend either using GraphQL (which brings documentation out of the box) or using a library like [tapir](https://github.com/softwaremill/tapir) (which can generate OpenAPI definitions).
For 0.5.x onward the scope of the project was reduced, so this will hopefully help me
keep up with updating dependencies and the like.## Goals
* Express swagger specifications in a reasonably type-safe DSL.
* Don't clutter models and logic with annotations
* Provide serialization for json and yaml using circe
* Avoid reflection
* Be reasonable to use in IDEs (e.g. IntelliJ)## Getting Started
### Dependencies
The library is published on Sonatype for both `Scala 2.11.11` and `Scala 2.12.6`:
```scala
resolvers += Resolver.sonatypeRepo("releases")
```There are serializers for json and yaml. The extensions also include the core lib, so
you only need to specify the extension you want to use:#### json (circe 0.9.3)
```scala
"io.github.felixbr" %% "swagger-blocks-json" % "0.6.0"
```
#### yaml (circe-yaml 0.8.0)
```scala
"io.github.felixbr" %% "swagger-blocks-yaml" % "0.6.0"
```#### There is of course also the core module available for the DSL and core data types alone:
```scala
"io.github.felixbr" %% "swagger-blocks-core" % "0.6.0"
```### Writing Swagger Path and Schema specifications
Write a specification for your endpoint (e.g. in your controller's companion
object):```Scala
import swaggerblocks._
import swaggerblocks.Implicits._object PetsController {
lazy val petListPath = swaggerPath("/pets")(
operations = List(
operation(GET)(
description = "Returns a list of pet objects",
summary = "Returns a list of pet objects",tags = List("pet"),
parameters = List(
queryParameter(
name = "tag",
required = false,
schema = t.string,
description = "tag to filter by"
)
),responses = List(
response(200)(
description = "pet response",
schema = manyOf(petSchema)
)
)
)
)
)lazy val petSchema = swaggerSchema("Pet")(
property("id")(
schema = t.integer
),property("name")(
schema = t.string,
description = "Name of the pet"
),property("tag")(
schema = t.string,
required = false
)
)```
### Rendering the output for swagger-ui
Create a new endpoint which serves the json needed for the swagger-ui. I
recommend to use the same controller which serves the ui. You also have to
write the required root metadata for swagger:```Scala
import swaggerblocks._
import swaggerblocks.Implicits._
import swaggerblocks.rendering.json.renderPretty// could be play or some other framework
class SwaggerController {lazy val petstoreRoot = swaggerRoot("2.0")(
host = "petstore.swagger.wordnik.com",
basePath = "/api",info(
version = "1.0.0",
title = "Swagger Petstore",
description = "A sample API that uses a petstore as an example",contact = contact(
name = "Wordnik API Team"
),license = license(
name = "MIT"
)
)
)val paths = List(
PetsController.petListPath
)
val schemas = List(
PetsController.petSchema
)def json = {
val swaggerJson: String = renderPretty(petstoreRoot, paths, schemas)// response with swaggerJson as content
}
}
```Now you only have to include the new action in your `routes` file and point
a swagger-ui (possibly rendered by a standard html-view) at the url.## Usage guide
### Providing a schema example
Since the example has to be embedded in the final json/yaml rendering this feature depends
on the rendering library you want to use. The extension method is located at
`swaggerblocks.extensions..ExampleExtension`. When is is imported, you can
call `.withExample` on the schema definition like shown below:```scala
import swaggerblocks._
import swaggerblocks.Implicits._
import swaggerblocks.extensions.json.ExampleExtensionimport io.circe.syntax._
import io.circe.generic.auto._lazy val schemaWithExample = swaggerSchema("SchemaWithExample")(
property("id")(
schema = t.integer
),
property("name")(
schema = t.string
)
).withExample(
Map(
"id" -> 123.asJson, // if the values in a map are not uniform, you have to be
"name" -> "Bello".asJson // explicit about it being serializable (or use a case class)
)
)// you can of course use all features provided by circe like
// case class serializationcase class Dog(id: Int, name: String)
lazy val schemaWithCaseClassExample = swaggerSchema("SchemaWithCaseClassExample")(
property("id")(
schema = t.integer
),
property("name")(
schema = t.string
)
).withExample(
Dog(123, "Fiffi")
)
```## Caveats
While for the most part the library API tries to stick to the swagger spec,
there are some exceptions made either for technical reasons, type-safety or
usability:* Since `type` is a restricted keyword you'll have to use `schema` in its place.
You can use primitive types (e.g. `schema = t.string`) as well as references to schemas
(e.g. `schema = petSchema`) and it will be sorted out behind the scenes.
* Many values in swagger can either be a primitive type, an object or a list of
the former two. In order to make this more type-safe
and usable, there is a `manyOf` helper for lists, which accepts primitive types
or schemas.
Because of type erasure you have to use `parameter.manyOf` instead of just `manyOf` for
all non-body parameters.
* Types are currently namespaced by `t` (e.g. `t.string`, `t.integer`, `t.number`).
Some types should only be used in certain places according to the swagger spec.
For example `t.file` is not allowed in path-parameters, but currently this is not enforced.
There are namespaces for the different parameters, so you can easily find the allowed
ones using autocompletion (e.g. `t.parameter.path.string` or `t.parameter.formData.file`).
* The DSL uses a few implicit conversions to provide an easier and more uniform way to write things.
For example most optional text fields like `description` still accept a `String` literal
due to an implicit `String => Option[String]`. The other conversions deal with differences
in `schema` fields.