PlantUML JSON/YAML visualization & math notation
PlantUML doesn’t only draw diagrams: it can render JSON, YAML, LaTeX math, and EBNF grammar as visual structures. These views are gold for READMEs, API docs, and syntax references.
JSON visualization Basic syntax 1 2 3 4 5 6 7 8 @startjson { "name": "Alice", "age": 30, "email": "alice@example.com", "isActive": true } @endjson
@startjson / @endjson wrap, automatically renders as a tree.
Nested 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @startjson { "id": "ORD-2026-001", "customer": { "id": 1024, "name": "Alice", "addresses": [ { "type": "home", "city": "Shanghai" }, { "type": "work", "city": "Beijing" } ] }, "items": [ { "sku": "P-001", "qty": 2, "price": 49.99 }, { "sku": "P-002", "qty": 1, "price": 99.00 } ], "total": 198.98, "status": "PAID" } @endjson
Real example: API response 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @startjson { "code": 0, "message": "success", "data": { "page": 1, "page_size": 20, "total": 153, "items": [ { "id": 1, "title": "PlantUML intro", "published_at": "2026-07-15T14:00:00Z", "tags": ["intro", "PlantUML"] }, { "id": 2, "title": "PlantUML theming", "published_at": "2026-07-29T14:05:00Z", "tags": ["theming", "class", "skinparam"] } ] } } @endjson
Put a real-looking payload in the API doc — far more readable than raw JSON.
Schema validator output 1 2 3 4 5 6 7 8 9 10 11 12 13 @startjson { "valid": true, "errors": [], "warnings": [ { "path": "$.customer.email", "message": "email format does not match RFC 5322", "expected": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" } ] } @endjson
YAML visualization Basic 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @startyaml apiVersion: apps/v1 kind: Deployment metadata: name: my-app labels: app: my-app env: production spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-app image: my-app:1.0 ports: - containerPort: 8080 env: - name: NODE_ENV value: production - name: DB_HOST value: db.internal resources: limits: memory: "512Mi" cpu: "500m" @endyaml
A Kubernetes Deployment config rendered as a tree.
App config 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @startyaml server: host: 0.0.0.0 port: 8080 timeout: 30s workers: 4 database: primary: host: db.internal port: 5432 name: appdb ssl: true replicas: - host: db-replica-1 port: 5432 name: appdb ssl: true redis: cluster: - redis-1:6379 - redis-2:6379 - redis-3:6379 ttl: 3600 logging: level: info format: json outputs: - stdout - file: /var/log/app.log rotation: max_size: "100MB" max_files: 10 @endyaml
CI/CD config 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @startyaml name: CI on: push: branches: [main, develop] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest strategy: matrix: node: [16, 18, 20] steps: - uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} - name: Install run: npm ci - name: Lint run: npm run lint - name: Test run: npm test - name: Build run: npm run build deploy: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - name: Deploy env: API_KEY: ${{ secrets.API_KEY }} run: ./deploy.sh @endyaml
JSON vs YAML
Dimension
JSON
YAML
Origin
JavaScript / Web API
Config files
Style
Compact, braces
Indent-sensitive
Comments
Not supported
Supported
Anchors
Partial
Full
PlantUML
@startjson
@startyaml
Common use
API responses, messages, config
K8s, CI, config files
Math (LaTeX) @startmath renders LaTeX math expressions:
1 2 3 @startmath $\sum_{i=0}^{n-1} (i+1) = \frac{n(n+1)}{2}$ @endmath
Algorithm analysis 1 2 3 @startmath $O(n \log n) = O(\log n!) = O\Big(\sum_{k=1}^{n} \log k\Big)$ @endmath
Machine learning 1 2 3 @startmath $J(\theta) = -\frac{1}{m} \sum_{i=1}^{m} \Big(y^{(i)} \log(h_\theta(x^{(i)})) + (1-y^{(i)}) \log(1-h_\theta(x^{(i)}))\Big) + \frac{\lambda}{2m} \sum_{j=1}^{n} \theta_j^2$ @endmath
Bayes 1 2 3 @startmath $P(A \mid B) = \frac{P(B \mid A) \, P(A)}{P(B)}$ @endmath
Matrices 1 2 3 @startmath $\begin{pmatrix} a & b \\ c & d \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = \lambda \begin{pmatrix} x \\ y \end{pmatrix}$ @endmath
EBNF @startebnf draws BNF / EBNF grammar as a railroad diagram:
1 2 3 4 5 6 @startebnf Expression ::= Term (("+" | "-") Term)* Term ::= Factor (("*" | "/") Factor)* Factor ::= Number | "(" Expression ")" Number ::= [0-9]+ @endstartebnf
Real: JSON grammar 1 2 3 4 5 6 7 8 9 10 @startebnf JSON-text ::= ws object ws object ::= '{' ws (member (',' ws member)*)? ws '}' ws member ::= string ws ':' ws value array ::= '[' ws (value (',' ws value)*)? ws ']' ws value ::= string | number | object | array | "true" | "false" | "null" string ::= '"' char* '"' number ::= '-'? (digit | non-zero-digit digit*) ('.' digit+)? ws ::= (space | newline | tab)+ @endstartebnf
Real: SQL SELECT grammar 1 2 3 4 5 6 7 8 9 10 @startebnf SELECT ::= "SELECT" column_list "FROM" table_name (where_clause)? (group_clause)? (order_clause)? (limit_clause)? column_list ::= "*" | column ("," column)* where_clause ::= "WHERE" condition group_clause ::= "GROUP BY" column ("," column)* order_clause ::= "ORDER BY" column ("ASC" | "DESC") limit_clause ::= "LIMIT" number condition ::= expression (("=" | "!=" | "<" | ">" | "<=" | ">=") expression)? expression ::= term (("AND" | "OR") term)* @endstartebnf
Real: URL grammar 1 2 3 4 5 6 7 8 9 10 11 12 13 @startebnf URL ::= scheme "://" host (":" port)? path? query? scheme ::= "http" | "https" | "ftp" host ::= domain ("." domain)* domain ::= alnum+ port ::= digit+ path ::= "/" segment ("/" segment)* segment ::= alnum+ query ::= "?" (param ("&" param)*)? param ::= key "=" value key ::= alnum+ value ::= alnum+ @endstartebnf
Real example: API docs in four diagrams Best API doc layout has four views:
1 2 3 4 5 docs/api/ list-articles.json.puml # @startjson list-articles-class.puml # @startuml class list-articles-sequence.puml # @startuml sequence list-articles-errors.puml # @startuml activity
Different .puml files render to different SVGs, fit into different doc sections.
Pick the right diagram
Data
Diagram
JSON response
@startjson
YAML config
@startyaml
Math formula
@startmath
EBNF grammar
@startebnf
Review checklist JSON / YAML
Math
EBNF
Anti-patterns 1. Wrapping JSON in @startuml 1 2 3 4 5 @startuml { "name": "alice" } @enduml
Wrong — PlantUML doesn’t recognize raw JSON; renders garbage. Wrap with @startjson.
2. Math without $$ 1 2 3 @startmath x^2 + y^2 = z^2 @endmath
LaTeX needs $..$ or $$..$$ delimiter; otherwise it’s just text.
3. EBNF terminals without quotes 1 2 3 @startebnf if-stmt ::= if ( condition ) statement @endstartebnf
if is a non-terminal concept but EBNF treats everything as terminal. Quote literals:
1 2 3 @startebnf if-stmt ::= "if" ( condition ) statement @endstartebnf