Mustache Templates in OpenAPI Generator — Template Engine Deep Dive
In this tutorial, you will learn about Mustache Templates in OpenAPI Generator. We cover key concepts, practical examples, and best practices to help you master this topic.
Mustache is the template engine powering OpenAPI Generator, providing a logic-less syntax for transforming OpenAPI spec models into source code across 50+ target languages and frameworks.
What You'll Learn
Mustache template syntax for OpenAPI Generator: variable interpolation, sections and conditionals, inverted sections, partials and template composition, custom renderer helpers, and advanced patterns for generating production-quality API client and server code.
Why It Matters
Mustache templates determine the exact output of every generated file. Understanding Mustache lets you customize generated code to match your team's style, add framework-specific patterns, and create entirely new generators. DodaTech's custom Mustache templates include OpenTelemetry tracing, structured logging, and health check endpoints in every generated service.
Real-World Use
DodaTech maintains a Mustache template library shared across 12 microservices. When the observability team adds a new metric, they update one Mustache partial and all 12 services get the change in the next code generation cycle.
flowchart LR
A["OpenAPI\nSpec Model"] --> B["Mustache\nTemplate"]
B --> C["Generated\nSource Code"]
D["Custom\nHelpers"] --> B
E["Partials\n(Shared)"] --> B
subgraph "Mustache Processing"
F["Variables: {{name}}"]
G["Sections: {{#list}}"]
H["Partials: {{>header}}"]
end
style B fill:#fef3c7,stroke:#d97706
style C fill:#bbf7d0,stroke:#16a34a
Mustache Syntax Reference
| Syntax | Purpose | Example |
|---|---|---|
{{var}} |
Variable interpolation | {{packageName}} |
{{{var}}} |
Unescaped variable | {{{description}}} |
{{#section}}...{{/section}} |
Truthy section | {{#hasVars}}...{{/hasVars}} |
{{^section}}...{{/section}} |
Inverted section | {{^vars}}...{{/vars}} |
{{>partial}} |
Include partial | {{>partials/header}} |
{{! comment }} |
Comment | {{! This is hidden }} |
{{.}} |
Current context | {{#items}}{{.}}{{/items}} |
Working with Sections
{{! Model template showing sections and conditionals }}
{{#models}}
{{#model}}
{{! Section renders only if model has vars }}
{{#hasVars}}
class {{classname}}:
{{#vars}}
{{#description}}
"""{{description}}"""
{{/description}}
{{name}}: {{datatype}}{{#required}} = None{{/required}}
{{/vars}}
{{#hasMore}}
# Additional properties exist
{{/hasMore}}
{{/hasVars}}
{{! Inverted section: no vars }}
{{^hasVars}}
class {{classname}}:
pass
{{/hasVars}}
{{/model}}
{{/models}}
Expected rendering for a model with three fields:
class Order:
"""Order information for a purchase"""
id: str
product_name: str
quantity: int
Using Partials for Reusable Components
{{! templates/partials/header.mustache }}
# {{packageName}}
# Auto-generated by OpenAPI Generator
# Do not edit this file manually
# Last generated: {{generatedDate}}
from __future__ import annotations
from typing import Optional, List
from pydantic import BaseModel
{{! templates/partials/common_imports.mustache }}
import datetime
import uuid
from enum import Enum
{{! Main controller template using partials }}
{{>partials/header}}
{{>partials/common_imports}}
class {{classname}}:
{{#vars}}
{{name}}: Optional[{{datatype}}] = None
{{/vars}}
{{#hasEnums}}
class {{enumName}}(str, Enum):
{{#allowableValues}}
{{#enumVars}}
{{name}} = "{{value}}"
{{/enumVars}}
{{/allowableValues}}
{{/hasEnums}}
Custom Renderer Helpers
OpenAPI Generator provides additional helpers beyond standard Mustache. These are implemented in Java and available in templates:
{{! Custom helpers available in OpenAPI Generator templates }}
{{! Lambda helpers transform values: }}
{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}
{{#lambda.camelcase}}{{paramName}}{{/lambda.camelcase}}
{{#lambda.snakecase}}{{propertyName}}{{/lambda.snakecase}}
{{#lambda.kebabcase}}{{serviceName}}{{/lambda.kebabcase}}
{{#lambda.firstname}}{{fullName}}{{/lambda.firstname}}
{{#lambda.lastname}}{{fullName}}{{/lambda.lastname}}
{{! Utility helpers: }}
{{#import}}
import {{import}}
{{/import}}
{{! Example: converting operation IDs to method names }}
{{#operations}}
{{#operation}}
{{#lambda.camelcase}}{{operationId}}{{/lambda.camelcase}}
{{/operation}}
{{/operations}}
Advanced Pattern: Nested Model Iteration
{{! Generate imports for all referenced models }}
{{#imports}}
{{#import}}
from {{packageName}}.models.{{import}} import {{import}}
{{/import}}
{{/imports}}
{{! Generate controller method for each operation }}
{{#apiInfo}}
{{#apis}}
{{#operations}}
{{#operation}}
async def {{#lambda.camelcase}}{{operationId}}{{/lambda.camelcase}}(
{{#allParams}}
{{paramName}}: {{#isRequired}}{{dataType}}{{/isRequired}}{{^isRequired}}Optional[{{dataType}}] = None{{/isRequired}},
{{/allParams}}
):
"""{{summary}}"""
{{#hasBodyParam}}
body_data = {{bodyParam.paramName}}.model_dump()
{{/hasBodyParam}}
{{#returnType}}
return {{returnType}}(**result)
{{/returnType}}
{{^returnType}}
return None
{{/returnType}}
{{/operation}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
Common Mistakes
1. Using {{.}} Incorrectly
{{.}} refers to the current context value, not the current object. Use it only inside iteration sections where the item is a primitive value. For objects, access properties by name.
2. Forgetting Section Closing Tags
Every {{#section}} must have a matching {{/section}}. Missing closing tags cause the rest of the template to render incorrectly. Use a Mustache validator to check template syntax.
3. Assuming {{#section}} Works Like if/else
Mustache sections are not if/else. A section renders when the value is truthy (non-empty list, non-null, true). Use {{^section}} for the falsey case. There is no elseif or logical operator.
4. Over-Nesting Templates
Deeply nested Mustache templates are hard to read and debug. Extract reusable blocks into partials. A template should rarely exceed 3 levels of nesting.
5. Ignoring Whitespace Control
Mustache includes whitespace in the output. A section that renders nothing still prints the surrounding whitespace. Use {{#section}}{{/section}} on the same line for compact output.
Practice Questions
- What is the difference between
{{var}}and{{{var}}}? - How do you create reusable template components?
- What is an inverted section and when do you use it?
- How do custom helpers like
{{#lambda.camelcase}}work?
Answers:
{{var}}HTML-escapes the output.{{{var}}}renders the raw value without escaping. Use{{{var}}}for code generation where HTML encoding would break syntax.- Reusable components are called partials, defined in separate .mustache files and included with
{{>partialName}}. Place them in the partials subdirectory of your template directory. - An inverted section
{{^condition}}...{{/condition}}renders content when the value is falsey (null, false, empty list). Use it for default values and empty state handling. - Custom helpers are Java-implemented lambda functions registered with the Mustache renderer. They transform values at render time.
{{#lambda.camelcase}}{{name}}{{/lambda.camelcase}}converts a string to camelCase.
Challenge: Create a custom Mustache template set for a fictional generator that outputs configuration files (YAML format) from an OpenAPI spec. Include templates for Docker Compose, Kubernetes deployment, and Terraform variables with proper partials.
FAQ
Mini Project
Extract the default Python FastAPI templates, identify and modify the model.mustache template to add JSON Serialization methods and validation decorators, create partials for common imports and utility functions, and regenerate code from a spec to verify the changes.
What's Next
Custom Templates — build a complete custom template set.
Generator Plugins — create plugins that extend code generation.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro