What is OpenAPI (and Swagger)?
OpenAPI is a way to describe web services API. Basically, it allows to define API routes (with path, allowed parameters, HTTP verb...) and models (object models corresponding to API response or body and its components). All this information is contained in an OpenAPI specification written in YAML or JSON.
You may have heard about Swagger and its visible part Swagger UI. OpenAPI is simply the new name of Swagger after it has been transferred to the open-source community.
What is OpenAPI Generator?
Since the OpenAPI specification contains everything needed to interact with the API, we can generate the code required to interact with the API based on this file. And since REST API often expose a large data model with dozens of entities, it's very tenting to generate them. For exemple, the Twitter API used in this article is composed of more than 180 entities that you would have to write by hand.
Fortunately, OpenAPI Generator can generate everything from the model classes to an entire Gradle module for your data layer!
Install OpenAPI Generator
Open API Generator can be integrated using a Gradle plugin, but during development, I recommend using the CLI client which is more convenient during the configuration of the project.
Get the OpenAPI specification for your web service
This is the part where there is no magic. If the backend is developed by a separate team, they should already give you a corresponding OpenAPI or Swagger specification as part of the webservice documentation.
The goal of this article is not to cover how to write an OpenAPI specification, so let's take an existing one!
As an example, we can get a public API specification from Twitter.
In a new directory, download the specification file:
$ wget https://api.twitter.com/2/openapi.json
Then, let’s generate some code based on this:
$ openapi-generator generate -g kotlin -i openapi.json
generate indicates that you want to generate something based on the
openapi.json file. The
-g option indicates the generator you want to use.
Dozens of languages and platforms are supported such as
python... You can see all supported generators with
$ openapi-generator list.
Run the command, and boom: An entire Kotlin SDK for Twitter has been generated!
There is now a complete standalone Gradle module with:
Gradle build files
API documentation (Markdown) in
API models in
Contains all model classes specified by the specification, and used by the endpoints. By default, Moshi JSON parser is used for serialization.
API methods in
Contains a method for every endpoint specified, using
OkHttpby default as a client.
And since comments are generated from the specification file, it’s probably more commented than hand-written code!
Generate only some parts of the module
Generating the whole module is a good starting point to see what’s available, but it may be difficult to integrate into your current architecture. For instance, you may already have a configured OkHttp instance to use, and want to use Retrofit. At the end, we may be only interested in generating the model classes and the API classes.
--global-property models --global-property apis options to generate only these classes.
As an example, wouldn’t it be nice to put these classes directly into your
app module? Let’s add more options:
-o app will target this directory for the generated code
--model-package "com.myapp.mydatalayer.entities" Allows control in which package the model classes are generated
--api-package "com.myapp.mydatalayer.api" will do the same for the API classes.
Customize your models
At this point we may not want to use Moshi as a parser. Want to use the fancy
kotlinx.serialization? Add this option:
jackson are also supported.
It is a good practice to identify at a glance if a model class is used in your data layer or your domain layer. Let’s add an
Entity suffix to allow that!
Now, all model classes end with this.
Customize API interface files
Now, we may want to use our good old friend Retrofit for the API.
Let’s add this to
To use Kotlin coroutines for the Retrofit interface:
additional-properties should be concatenated using
,our final option looks like:
Use custom templates
If you tried to compile the module at the previous steps, you may have found that it, unfortunately, doesn’t compile 😭. As meta-programming is very powerful, it’s also a common pitfall you may encounter, so let’s try to fix this!
OpenAPI-generator works with templates written with the mustache template language. To access the templates used previously, use the
author template command.
$ openapi-generator author template -g kotlin -o template
You can then browse the template directory. Some interesting files:
data_class_req_var.mustacheare used to generate the models.
libraries/jvm-retrofit2/api.mustacheis used to generate the Retrofit API interfaces that we configured previously.
licenseInfo.mustacheis the header for the model classes.
Finally, we want to be able to generate the file on demand without having to install the CLI client.
The OpenAPI Generator Gradle plugin make it possible!
After having setup the plugin,
Let’s convert the command line we’ve been methodically building to a set of option:
globalProperties = [
apis : "",
models : "",
inputSpec = "openapi.json"
generatorName = "kotlin"
outputDir = "$rootDir/app"
templateDir = "template"
modelPackage = "fr.haan.openapi_playground_app.data.entities"
apiPackage = "fr.haan.openapi_playground_app.data.api"
modelNameSuffix = "Entity"
additionalProperties = [
useCoroutines : "true",
library : "jvm-retrofit2",
sourceFolder : "src/main/java",
We can now generate using gradle CLI:
$ ./gradlew openApiGenerate
That’s it! Our app is now ready to follow the backend REST API developments without having to manually write entities or interfaces!
As you can see, a lot of power comes from the spec being perfectly written (with strong types, accurate documentation, etc...) I guess the best way to achieve this is to also generate the server side using the same specification.
Anyway, I hope you enjoyed reading this! You will find the complete step-by-step repository with all the example code of this article here.