Skip to main content

Tools

There are numerous tools to help with OpenAPI.

We can search for some at:

SwaggerHub offers a whole suite for this with code generators and everything else, take an overview there later and see if it works for you. Regardless of everything it's always good to know things.

Let's talk about OpenAPI Generator which despite this name includes several features beyond code generation. The OpenAPI Generator repository on Github can also be useful to help.

The advantage of using tools like this is the number of sponsors it has. Going straight to the official documentation we have several ways to use it.

Already with the tool installed in the terminal we have the following:

❯ openapi-generator --version
openapi-generator-cli 7.10.0
commit : 12dfe8f
built : -999999999-01-01T00:00:00+18:00
source : https://github.com/openapitools/openapi-generator
docs : https://openapi-generator.tech/

❯ openapi-generator
usage: openapi-generator-cli <command> [<args>]

The most commonly used openapi-generator-cli commands are:
author Utilities for authoring generators or customizing templates.
batch Generate code in batch via external configs.
config-help Config help for chosen lang
generate Generate code with the specified generator.
help Display help information about openapi-generator
list Lists the available generators
meta MetaGenerator. Generator for creating a new template set and configuration for Codegen. The output will be based on the language you specify, and includes default templates to include.
validate Validate specification
version Show version information used in tooling

See 'openapi-generator-cli help <command>' for more information on a specific
command.

For those who don't want to install the tool can use docker. The openapi-generator command is the entrypoint of the container. Make an alias in your shell, it's an interesting proposal too.

docker run --rm \
-v ${PWD}:/local openapitools/openapi-generator-cli
usage: openapi-generator-cli <command> [<args>]

The most commonly used openapi-generator-cli commands are:
author Utilities for authoring generators or customizing templates.
batch Generate code in batch via external configs.
config-help Config help for chosen lang
generate Generate code with the specified generator.
help Display help information about openapi-generator
list Lists the available generators
meta MetaGenerator. Generator for creating a new template set and configuration for Codegen. The output will be based on the language you specify, and includes default templates to include.
validate Validate specification
version Show version information used in tooling

See 'openapi-generator-cli help <command>' for more information on a specific
command.

We already used it to validate the api we made, but let's use it again to remember

# Everything ok
❯ openapi-generator validate -i infoapi.yaml
Validating spec (infoapi.yaml)
No validation issues detected.

Forcing an error to test.

security:
# - BasicAuth: []
# - JwtAuthToken: []

I'll do it using docker to understand the process.

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli validate -i /local/infoapi.yaml
Validating spec (/local/infoapi.yaml)
Errors:
- attribute security is not of type `array`

[error] Spec has 1 errors.

We can generate code from this api. The list is available here and we can see it via cli.

openapi-generator list
The following generators are available:

CLIENT generators:
- ada
- android
- apex
- bash
- c
- clojure
- cpp-qt-client
- cpp-restsdk
- cpp-tiny (beta)
- cpp-tizen
- cpp-ue4 (beta)
- crystal (beta)
- csharp
- dart
- dart-dio
- eiffel
- elixir
- elm
- erlang-client
- erlang-proper
- gdscript
- go
- groovy
- haskell-http-client
- java
- java-helidon-client (beta)
- java-micronaut-client (beta)
- javascript
- javascript-closure-angular (beta)
- javascript-flowtyped
- jaxrs-cxf-client
- jetbrains-http-client (experimental)
- jmeter
- julia-client (beta)
- k6 (beta)
- kotlin
- lua (beta)
- n4js (beta)
- nim (beta)
- objc
- ocaml
- perl
- php
- php-dt (beta)
- php-nextgen (beta)
- powershell (beta)
- python
- python-pydantic-v1
- r
- ruby
- rust
- scala-akka
- scala-gatling
- scala-http4s
- scala-pekko
- scala-sttp
- scala-sttp4 (beta)
- scalaz
- swift-combine
- swift5
- swift6 (beta)
- typescript (experimental)
- typescript-angular
- typescript-aurelia
- typescript-axios
- typescript-fetch
- typescript-inversify
- typescript-jquery
- typescript-nestjs (experimental)
- typescript-node
- typescript-redux-query
- typescript-rxjs
- xojo-client
- zapier (beta)


SERVER generators:
- ada-server
- aspnet-fastendpoints
- aspnetcore
- cpp-pistache-server
- cpp-qt-qhttpengine-server
- cpp-restbed-server
- cpp-restbed-server-deprecated
- csharp-functions
- erlang-server
- fsharp-functions (beta)
- fsharp-giraffe-server (beta)
- go-echo-server (beta)
- go-gin-server
- go-server
- graphql-nodejs-express-server
- haskell
- haskell-yesod (beta)
- java-camel
- java-helidon-server (beta)
- java-inflector
- java-micronaut-server (beta)
- java-microprofile
- java-msf4j
- java-pkmst
- java-play-framework
- java-undertow-server
- java-vertx-web (beta)
- java-wiremock (beta)
- jaxrs-cxf
- jaxrs-cxf-cdi
- jaxrs-cxf-extended
- jaxrs-jersey
- jaxrs-resteasy
- jaxrs-resteasy-eap
- jaxrs-spec
- julia-server (beta)
- kotlin-server
- kotlin-spring
- kotlin-vertx (beta)
- kotlin-wiremock (beta)
- nodejs-express-server (beta)
- php-flight (experimental)
- php-laravel
- php-lumen
- php-mezzio-ph
- php-slim4
- php-symfony
- python-aiohttp
- python-blueplanet
- python-fastapi (beta)
- python-flask
- ruby-on-rails
- ruby-sinatra
- rust-axum (beta)
- rust-server
- scala-akka-http-server (beta)
- scala-cask
- scala-finch
- scala-http4s-server
- scala-lagom-server
- scala-play-server
- scalatra
- spring


DOCUMENTATION generators:
- asciidoc
- cwiki
- dynamic-html
- html
- html2
- markdown (beta)
- openapi
- openapi-yaml
- plantuml (beta)


SCHEMA generators:
- avro-schema (beta)
- graphql-schema
- ktorm-schema (beta)
- mysql-schema
- postman-collection (beta)
- protobuf-schema (beta)
- wsdl-schema (beta)


CONFIG generators:
- apache2

Now let's generate code from the API specification we have. Each language we want to generate code offers us different types of customizations. The configuration for code generation in go can also be seen via CLI.

❯ openapi-generator config-help -g go

CONFIG OPTIONS

disallowAdditionalPropertiesIfNotPresent
If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default. (Default: true)
false - The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.
true - Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.

enumClassPrefix
Prefix enum with class name (Default: false)

generateInterfaces
Generate interfaces for api classes (Default: false)

generateMarshalJSON
Generate MarshalJSON method (Default: true)

generateUnmarshalJSON
Generate UnmarshalJSON method (Default: true)

hideGenerationTimestamp
Hides the generation timestamp when files are generated. (Default: true)

isGoSubmodule
whether the generated Go module is a submodule (Default: false)

packageName
Go package name (convention: lowercase). (Default: openapi)

packageVersion
Go package version. (Default: 1.0.0)

prependFormOrBodyParameters # We'll use this in the example soon.
Add form or body parameters to the beginning of the parameter list. (Default: false)

structPrefix
whether to prefix struct with the class name. e.g. DeletePetOpts => PetApiDeletePetOpts (Default: false)

useDefaultValuesForRequiredVars
Use default values for required variables when available (Default: false)

useOneOfDiscriminatorLookup
Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. (Default: false)

withAWSV4Signature
whether to include AWS v4 signature support (Default: false)

withGoMod
Generate go.mod and go.sum (Default: true)

withXml
whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML) (Default: false)

A command that is good to know and although it is not in the CLI is completion which helps us use the CLI better.

# What can we do from validate?
❯ openapi-generator completion validate
--recommend
-i
--input-spec

❯ openapi-generator validate -i infoapi.yaml --recommend
Validating spec (infoapi.yaml)
Warnings:
- While technically allowed, GET/HEAD with request body may indicate programming error, and
is considered an anti-pattern.

[info] Spec has 1 recommendation(s).

##### ---------

❯ openapi-generator completion list
-s
--short
-i
--include
-d
--docsite
--github-nested-index


❯ openapi-generator list -s
ada,ada-server,android,apache2,apex,asciidoc,aspnet-fastendpoints,aspnetcore,avro-schema,bash,crystal,c,clojure,cwiki,cpp-qt-client,cpp-qt-qhttpengine-server,cpp-pistache-server,cpp-restbed-server,cpp-restbed-server-deprecated,cpp-restsdk,cpp-tiny,cpp-tizen,cpp-ue4,csharp,csharp-functions,dart,dart-dio,eiffel,elixir,elm,erlang-client,erlang-proper,erlang-server,fsharp-functions,fsharp-giraffe-server,gdscript,go,go-echo-server,go-server,go-gin-server,graphql-schema,graphql-nodejs-express-server,groovy,kotlin,kotlin-server,kotlin-spring,kotlin-vertx,kotlin-wiremock,ktorm-schema,haskell-http-client,haskell,haskell-yesod,java,jaxrs-cxf-client,java-helidon-client,java-helidon-server,java-inflector,java-micronaut-client,java-micronaut-server,java-msf4j,java-pkmst,java-play-framework,java-undertow-server,java-vertx-web,java-camel,jaxrs-cxf,jaxrs-cxf-extended,jaxrs-cxf-cdi,jaxrs-jersey,jaxrs-resteasy,jaxrs-resteasy-eap,jaxrs-spec,javascript,javascript-flowtyped,javascript-closure-angular,java-wiremock,jetbrains-http-client,jmeter,julia-client,julia-server,k6,lua,markdown,java-microprofile,mysql-schema,n4js,nim,nodejs-express-server,objc,ocaml,openapi,openapi-yaml,plantuml,perl,php,php-flight,php-nextgen,php-laravel,php-lumen,php-slim4,php-symfony,php-mezzio-ph,php-dt,postman-collection,powershell,protobuf-schema,python,python-pydantic-v1,python-fastapi,python-flask,python-aiohttp,python-blueplanet,r,ruby,ruby-on-rails,ruby-sinatra,rust-axum,rust,rust-server,scalatra,scala-akka,scala-cask,scala-pekko,scala-akka-http-server,scala-finch,scala-gatling,scala-http4s,scala-http4s-server,scala-lagom-server,scala-play-server,scala-sttp,scala-sttp4,scalaz,spring,dynamic-html,html,html2,swift5,swift6,swift-combine,typescript,typescript-angular,typescript-aurelia,typescript-axios,typescript-fetch,typescript-inversify,typescript-jquery,typescript-nestjs,typescript-node,typescript-redux-query,typescript-rxjs,wsdl-schema,xojo-client,zapier

You must have noticed that we have generation both on the client side and on the server side. Obviously the code generated for the client side is different from the code generated for the server side.

Let's get to know this command a little better but we can also consult the generate documentation.

# You will notice that it shows both short and full commands.
❯ openapi-generator completion generate
-e
--engine
-a
--auth
--global-property
--library
-v
--verbose
--schema-mappings
--enable-post-process-file
--skip-validate-spec
--inline-schema-options
--server-variables
--artifact-id
--api-name-suffix
--operation-id-name-mappings
-c
--config
--release-note
-g # We'll use
--generator-name
--generate-alias-as-model
-s
--skip-overwrite
--name-mappings
--enum-name-mappings
--log-to-stderr
--git-repo-id
--legacy-discriminator-behavior
--instantiation-types
--invoker-package
--model-package
--ignore-file-override
-o
--output
--model-name-suffix
--parameter-name-mappings
--api-package
--model-name-mappings
--git-host
--strict-spec
--type-mappings
--git-user-id
--merged-spec-filename
--openapi-generator-ignore-list
--openapi-normalizer
-p
--additional-properties
--minimal-update
--remove-operation-id-prefix
--dry-run
--language-specific-primitives
--skip-operation-example
--http-user-agent
-t
--template-dir
--model-name-prefix
--inline-schema-name-mappings
--reserved-words-mappings
--import-mappings
--artifact-version
--group-id
--input-spec-root-directory
--package-name
-i
--input-spec

For example, we saw that we have in go the configuration option prependFormOrBodyParameters that I marked up there. To change this option we can set it directly in the command.

# --dry-run is just a simulation to not execute and see if the command works and what our output would be
openapi-generator-cli generate -g go --additional-properties=prependFormOrBodyParameters=true -o ./out -i infoapi.yaml --dry-run
# To pass multiple options --additional-properties=key1=value1,key2=value2

But you can't keep doing this. Create a file generatorconfig-go.yaml with the parameter configuration and we'll point to it.

prependFormOrBodyParameters: true
# key2: value2
# key3: value3
❯ openapi-generator generate -i infoapi.yaml -g go -c generatorconfig-go.yaml  -o ./goproject --dry-run

You can still move all the arguments we made above to a yaml or json file using batch. I won't document it here but it's good to know.

Depending on the chosen generator we will generate code on the client side or on the server side.

Generating code in go on the server side we need to use the generator go-server.

❯ openapi-generator generate -i infoapi.yaml -g go-server  -o ./go-server
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/Users/davidprata/Desktop/gitlab/devsecops/docs/development/openapi//docs/development/openapi/resources/./go-server) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: go-server (server)
### ... REMOVED TO FACILITATE READING

Now generating on the client side we will use the generator go.

❯ openapi-generator generate -i infoapi.yaml -g go  -o ./go-client
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/Users/davidprata/Desktop/gitlab/devsecops/docs/development/openapi//docs/development/openapi/resources/./go-client) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: go (client)
[main] INFO o.o.codegen.DefaultGenerator - Generator 'go' is considered stable.
### ... REMOVED TO FACILITATE READING
# Different files for different projects
ls go-client
README.md docs model_beer_order.go model_paged_response_pageable.go
api git_push.sh model_beer_order_line.go model_paged_response_pageable_sort.go
api_beer.go go.mod model_beer_paged_list.go response.go
api_customer.go go.sum model_brewery.go test
api_order_service.go model__v1_customers__customer_id__orders_post_request.go model_customer.go utils.go
client.go model_address.go model_customer_paged_list.go
configuration.go model_beer.go model_paged_response.go

ls go-server
Dockerfile README.md api go go.mod main.go