Spider-Gazelle has the ability to ouput OpenAPI descriptions of the routes defined in your service.
The source code is required to output OpenAPI as we extract descriptions from regular comments. The simplest way to generate the OpenAPI YAML is to:
- build the application
- generate the OpenAPI output
- If you would like a file then run
./bin/app --docs > ./bin/description.yml
You can then serve this document from your service when it's deployed if desirable.
class OpenAPI < AC::Base base "/openapi" DOCS = ActionController::OpenAPI.generate_open_api_docs( title: "Application", version: "0.0.1", description: "App description for OpenAPI docs" ).to_yaml get "/docs" do render yaml: DOCS end end
then visit your documentation at "http://localhost:3000/openapi/docs"
For optimal output it's recommended that you:
- decorate your route functions with return types (assumes no body if not decorated)
- decorate your models to improve JSON schema
class Comments < Application base "/comments" # description of your model that will be used in the OpenAPI output class Comment include JSON::Serializable # add format information to the output schema @[JSON::Field(format: "email")] property reply_to : String property user_id : Int64 property text : String end # This is a route summary @[AC::Route::GET("/:comment_id")] def show(comment_id : Int64) : Comment Comment.find(comment_id) end end
Summary and descriptions are extracted from the comments above the function that represents the route.
- the first line of the comment is used as a summary
- if there are multiple lines then all the lines are used as a description
class Comments < Application base "/comments" # This is a route summary @[AC::Route::GET("/")] def index; end # This is a route summary # This is a route description # and the description continued @[AC::Route::POST("/")] def create; end end
JSON schema is automatically extracted for all the types being serialised / deserialised including:
- Parameters (route and query)
- Request bodies
- Response bodies
For JSON::Serializable types you can include additional information.
class Comment include JSON::Serializable # add format information to the output schema @[JSON::Field(format: "email")] property reply_to : String property user_id : Int64 @[JSON::Field(format: "email")] property text : String # The `EpochConverter` here means the JSON value will actually be an integer # to avoid the schema output being `type: "string", format: "date-time"` you can # supply a type override and custom format string. @[JSON::Field(converter: Time::EpochConverter, type: "integer", format: "Int64")] getter time : Time end
Some of the
@[JSON::Field] annotations you can use are:
as per the JSON Schema spec
If your model doesn't use
JSON::Serializable and instead is using a custom serializer then you can implment
def self.json_schema(openapi : Bool? = nil) to return a
NamedTuple with the JSON Schema representation of your model.