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!