PlantUML JSON / YAML 数据可视化与数学公式
PlantUML 不只能画图:它还能把 JSON、YAML 数据本身画成可视化的树形结构,以及绘制 LaTeX 数学公式和 EBNF 语法图。这几类图在 README、API 文档、语法参考资料里非常好用。
JSON 可视化
基本用法
1 2 3 4 5 6 7 8
| @startjson { "name": "Alice", "age": 30, "email": "alice@example.com", "isActive": true } @endjson
|
@startjson / @endjson 包起来,自动渲染为树状图。每个字段都用一行表示。
嵌套
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
|
展示一个完整订单 JSON,比直接粘贴好看得多。
真实场景:API 响应示例
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 入门", "published_at": "2026-07-15T14:00:00Z", "tags": ["入门", "PlantUML"] }, { "id": 2, "title": "PlantUML 主题实战", "published_at": "2026-07-29T14:05:00Z", "tags": ["主题", "类图", "皮肤"] } ] } } @endjson
|
API 文档里放一段,比纯 JSON 容易读。
JSON Schema 验证示例
1 2 3 4 5 6 7 8 9 10 11 12 13
| @startjson { "valid": true, "errors": [], "warnings": [ { "path": "$.customer.email", "message": "邮箱格式不是 RFC 5322 标准", "expected": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" } ] } @endjson
|
展示验证器输出,调试 API 集成时方便。
YAML 可视化
基本用法
实际 YAML 用法
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
| @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
|
Kubernetes 部署 YAML 一图看明白。
应用配置
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
|
嵌套层次的可视化比配置文件原文好读。
GitLab CI / GitHub Actions 配置
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
|
CI/CD 配置一图复习。
JSON 与 YAML 的对比
| 维度 |
JSON |
YAML |
| 起源 |
JavaScript / Web API |
配置文件 |
| 风格 |
紧凑、花括号 |
缩进、缩进敏感 |
| 注释 |
不支持 |
支持 |
| 锚点 |
部分 |
完整 |
| PlantUML |
@startjson |
@startyaml |
| 典型用法 |
API 响应、配置、消息 |
K8s / CI / 配置文件 |
数学公式(LaTeX)
@startmath 让 PlantUML 渲染 LaTeX 数学表达式:
1 2 3
| @startmath $\sum_{i=0}^{n-1} (i+1) = \frac{n(n+1)}{2}$ @endmath
|
实战:算法分析
1 2 3
| @startmath $O(n \log n) = O(\log n!) = O\Big(\sum_{k=1}^{n} \log k\Big)$ @endmath
|
实战:机器学习
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
|
贝叶斯公式
1 2 3
| @startmath $P(A \mid B) = \frac{P(B \mid A) \, P(A)}{P(B)}$ @endmath
|
矩阵
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 把 BNF / EBNF 语法定义绘制为铁路图:
1 2 3 4 5 6
| @startebnf Expression ::= Term (("+" | "-") Term)* Term ::= Factor (("*" | "/") Factor)* Factor ::= Number | "(" Expression ")" Number ::= [0-9]+ @endstartebnf
|
实战:JSON 语法的 EBNF
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
|
实战:SQL SELECT 语法
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
|
实战:URL 语法
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
|
实战:API 文档全套
一个完整的 API 文档应该放 4 类图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @startuml title 文章列表 API 文档
== JSON 响应 == @startjson { "code": 0, "data": { "items": [{ "id": 1, "title": "..." }], "total": 153 } } @endjson
@enduml
|
放在同一个 .puml 里被 @startuml / @startuml 包起来会用 mixed contents。
实际操作中用单独的图 / 单独的 .puml 文件:
1 2 3 4
| docs/api/ list-articles.json.puml # @startjson list-articles-class.puml # @startuml class list-articles-sequence.puml # @startuml sequence
|
不同 .puml 文件渲染为多个 SVG,方便嵌入不同的文档位置。
选最佳图
| 数据 |
推荐图 |
| JSON 响应 |
@startjson |
| YAML 配置 |
@startyaml |
| 数学公式 |
@startmath |
| EBNF 语法 |
@startebnf |
评审 checklist
JSON / YAML
math
EBNF
反模式
1. JSON 包在 @startuml 里
1 2 3 4 5
| @startuml { "name": "alice" } @enduml
|
错的。植物uml 包 JSON 时不识别它是 JSON,会渲染出乱码。用 @startjson 包。
2. math 不写 $$
1 2 3
| @startmath x^2 + y^2 = z^2 @endmath
|
LaTeX 必须用 $$..$$ 或 $...$ 包裹。
3. EBNF 终结符不引号
1 2 3
| @startebnf if-stmt ::= if ( condition ) statement @endstartebnf
|
if 是非终结符,但 EBNF 默认全部按终结符处理。应该写:
1 2 3
| @startebnf if-stmt ::= "if" ( condition ) statement @endstartebnf
|
终结符必须加引号。