Photo by Denise Johnson on Unsplash
Mustache templates with OpenAPI specs
Best features of the OpenAPI code generation
This article explores the Mustache templates, in the context of the OpenAPI specification, and the underrated features that can help developers in optimizing the code generation.
At Adyen, we adopted OpenAPI specs some time ago and we have created our own Mustache templates to streamline the generation of the Adyen SDKs (in various languages) every time there is a new release of the payment APIs.
Mustache is a logic-less template framework used to generate output that must conform to a structure and format we want to control. The applications are several: generating code, HTML, configuration files, etc…
They are logic-less (meaning the actual templating engine must take care of the conversion logic), simple (having just the features you need — no-frills) and open-source.
In a nutshell
Given a template
Hello {{name}} {{lastname}}
and a data structure
{
"name": "Beppe",
"lastname": "Catanese"
}
the template engine will know how to produce
Hello Beppe Catanese
OpenAPI language templates
The OpenAPI Generator project allows the generation of (client, server and models) code starting from a valid OpenAPI specification, either json
or yaml
. This is an extremely valuable feature for API-driven products where code and API specs change often and need to be kept aligned (at ideally small effort).
In this workflow Mustache templates play a key role: for each language and framework OpenAPI provides a default implementation (based on predefined Mustache templates) which works really well in most cases and can be tuned further (extending the templates) when needed.
Becoming a Mustache Master
Let’s dive into the more advanced features that make Mustache templates powerful.
Parameters list
Use ^last
to add the comma between parameters unless it is the last one
{{#allParams}}paramName *{{{dataType}}}{{^-last}}, {{/-last}}{{/allParams}}
-> user *string, address *string, nationality *string
Naming parameters with a sequence
Use -index
to access the index while traversing an array or list
{{#allParams}}req{{-index}} *{{{dataType}}}{{^-last}}, {{/-last}}{{/allParams}}
-> req1 *string, req2 *string, req3 *string
Distinguish between parameters
While allParams
gives access to the whole list of parameters, it is useful to make a distinction when generating method signatures or documentation
{{#pathParams}}...{{/pathParams}}
{{#bodyParams}}...{{/bodyParams}}
{{#queryParams}}...{{/queryParams}}
Comments
Comments are useful in templates too, but rarely seen
/**
Info about the method
{{! comments to be ignore when parsing the template}}
**/
Custom delimiter
The default delimiters {{
and }}
can be overridden (some scripting languages use brace brackets). This is convenient when you need to include curly braces in your output.
{{! change delimiters to <% and %>}}
{{=<% %>=}}
{{! put it back }}
<%={{ }}=%>
First and last element
While traversing arrays it is useful to access easily the first and the last element, for example, the Go imports group all modules in a list starting and finishing with parenthesis
{{#-first}}
import (
{{/-first}}
"{{import}}"
{{#-last}}
)
{{/-last}}
-> import (
"fmt"
"math"
)
Lambda functions
There is a small set of functions available during the OpenAPI code generation: those are convenient when you need to lowercase a package name or camelCase a method.
lowercase(Beppe) -> beppe
uppercase(Beppe) -> BEPPE
titlecase(Beppe likes mustache) -> Beppe Likes Mustache
camelcase(Beppe-Catanese) -> BeppeCatanese
indented -> add indentation
Create custom generator
When specific customisation is necessary OpenAPI code generation allows to extend the specific-language generator to add (or redefine) the generation logic. The approach by extension is pretty straightforward:
1: extend the client code generator (for example implementing the renaming of the operationId
attribute)
2: generate the code using the new generator
Generate the client code using the new CodeGen implementation
java -jar openapi-generator-cli.jar generate \
-i /openapi.yaml -t templates/go -g go \
-p packageName=Checkout -o src/checkout \
-g org.mycompany.codegen.MyGoClientCodegen
Conclusion
Check out our Go Library to see the customisation of the Mustache templates and how the code generation is performed starting from the Adyen OpenAPI specs. Get ready for more articles and insights about our work with OpenAPI (i.e. generating server stubs, testing, mocking and validation).
Lateeeeeer!