PlantUML JSON/YAML visualization & math notation

puml.online

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

  • Correct fence (@startjson vs @startyaml)?
  • Indent keeps tree clean?
  • Nesting ≤ 4 levels?

Math

  • $...$ delimiter used?
  • Complex formulas split into lines?

EBNF

  • Terminals (literals) quoted?
  • Non-terminals capitalized?
  • Alternatives separated by |?

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
  • Title: PlantUML JSON/YAML visualization & math notation
  • Author: puml.online
  • Created at : 2026-07-29 16:00:00
  • Updated at : 2026-08-14 21:34:29
  • Link: https://puml.online/blog/plantuml-json-yaml-data-en/
  • License: This work is licensed under CC BY-NC-SA 4.0.