YAML 格式化完全指南:缩进、多文档与 JSON 互转
K8s 清单 apply 失败、GitHub Actions 报错「mapping values are not allowed here」,或同事发来一份 Tab 混空格的 docker-compose 时,最先该做的不是改业务字段,而是把 YAML 校验并摊平成统一缩进。本指南讲清缩进与类型陷阱、多文档边界、YAML 与 JSON 差异,给出可操作步骤与排错表,直接对接 WebUtils 本地 YAML 工具。
核心一句话
YAML 用缩进表达结构;空格错一位,语义就可能整段错位。
先确认能被解析,再美化或压缩;需要给程序或 API 用时,再转成 JSON。多文档、锚点引用、flow 风格与「看起来像数字的字符串」是最常见翻车点。下面按「规则 → 与 JSON 对照 → 操作 → 错误表 → 场景 → 选型」展开,可在 YAML 格式化 上对照练习。
1. YAML 在工程里到底管什么
YAML(YAML Ain't Markup Language)是面向人的数据序列化语言,广泛出现在:
- 容器与编排:
docker-compose.yml、Kubernetes Deployment / Service - CI/CD:GitHub Actions、GitLab CI、部分 Jenkins 配置
- 应用配置:Spring 的
application.yml、Ansible playbook、Helm values - 内容与元数据:部分静态站点 frontmatter、OpenAPI 的 YAML 形态
它的卖点是 可读:少括号、可注释、层级靠缩进。代价是 对空白极度敏感,且同一段文本在不同解析器(PyYAML、js-yaml、Go yaml.v3、SnakeYAML)上对「重复键、锚点、类型猜测」的行为不完全一致。
| 能力 | YAML 通常有 | JSON 通常有 | 调试时注意 |
|---|---|---|---|
注释 # |
有 | 无 | 美化后再转 JSON 会丢掉注释 |
多文档 --- |
有 | 无(单根值) | 一次 load 可能只吃第一段 |
锚点 & / 别名 * |
有 | 无 | dump 时可能展开或报 ref |
| 未加引号的字符串 | 有 | 必须加引号 | yes/on/1.0 可能被猜成布尔或数字 |
| 缩进表达层级 | 必须 | 靠 {} [] |
Tab 与空格混用是经典事故 |
本站工具基于浏览器内的 js-yaml:输入框粘贴后可实时校验;「美化 YAML」用 dump 以 2 空格重写;「压缩」走 flow 风格;并支持 YAML↔JSON。处理在本地完成,粘贴含密钥的配置前仍应脱敏。
2. 缩进、标量与列表:必须刻进肌肉记忆的规则
只用空格,不要用 Tab
YAML 1.1/1.2 实践中,缩进应使用空格。编辑器若把 Tab 显示成「看起来对齐」,解析器仍可能报错或层级错乱。团队应统一 2 空格(K8s/GitHub Actions 常见)或 4 空格,并在编辑器开启「以空格代替 Tab」。
同级对齐,子级多缩进一级
# 合法:同级键左缘对齐,子键多 2 空格
server:
host: localhost
port: 8080
ssl:
enabled: true
下面是故意非法的示例(子键比父键还靠左,或同级不对齐):
# 故意非法 server: host: localhost port: 8080
列表项的 - 位置
- 后一般有一个空格;列表项下的嵌套映射要与内容列对齐:
containers:
- name: web
image: nginx:1.25
- name: sidecar
image: busybox
字符串何时必须加引号
| 情况 | 建议 | 原因 |
|---|---|---|
含 : 后跟空格 |
加引号 | 易被当成「新的键值对」 |
以 { [ 开头的文本 |
加引号 | 易被当成 flow 集合 |
| 看起来像布尔/空 | 加引号 | yes/no/true/null 可能被类型化 |
版本号 1.10 |
视解析器 | 可能变成浮点 1.1 |
含 # 的行内文本 |
加引号 | # 开启注释 |
# 危险:某些解析器会把 yes 当成 true feature_flag: yes # 更稳妥 feature_flag: "yes" version: "1.10" message: "error: not found"
多文档与文档头
--- 分隔多个文档;... 可结束文档(较少手写)。K8s 里一份清单常含多个资源,用多文档拼在一个文件里。
apiVersion: v1 kind: ConfigMap metadata: name: app-config --- apiVersion: v1 kind: Secret metadata: name: app-secret
工具边界: 页面校验使用 jsyaml.load,对多文档字符串可能只解析第一段或直接报错,取决于输入形态。多文档清单建议:分段粘贴校验,或先确认你的目标运行时(kubectl)如何加载;不要假设「网页一次 load = kubectl apply 全部文档」。
3. YAML 与 JSON:差异与有损点
两者常互转,但不是信息论上的完全等价。
| 主题 | YAML | JSON | 互转时 |
|---|---|---|---|
| 注释 | 支持 | 不支持 | YAML→JSON 注释消失 |
| 键顺序 | 多数实现保留插入序 | 文本有序,语义上对象无序 | 一般可接受 |
| 数字与字符串 | 常自动猜测 | 类型由字面量决定 | "01" / 01 易踩坑 |
| 多文档 | 支持 | 单值 | 转 JSON 常只保留一个根 |
| 锚点合并 | 支持 | 无 | dump 常展开为重复结构 |
null / ~ / 空 |
多种写法 | 只有 null |
转回 YAML 风格可能变 |
何时留在 YAML: 给人读的配置、需要注释与锚点复用、编排与 CI 清单。 何时转 JSON: 接口调试、前端 JSON.parse、需要与 JSON 格式化 / Diff 工具链对接。 专用转换页: 若你的主任务就是反复 JSON↔YAML 且不强调「YAML 美化风格」,可用 JSON ↔ YAML;本篇主工具把校验 + 美化 + 压缩 + 互转放在同一屏,适合排错时少开标签页。
前后对照:同一结构两种写法
YAML:
user:
id: 1001
name: Ada
roles:
- admin
- editor
active: true
等价 JSON:
{
"user": {
"id": 1001,
"name": "Ada",
"roles": ["admin", "editor"],
"active": true
}
}
把 YAML 里的 active: yes 转成 JSON 后,可能变成 true 而不是字符串 "yes"——这是类型猜测,不是格式化「弄坏了字段名」。
4. 用 WebUtils 处理 YAML:逐步操作
工具页:YAML 格式化。
- 打开页面。 进入 /tools/dev/yaml-formatter,左侧为「输入 YAML / JSON」,右侧为「处理结果」。
- 粘贴内容。 可点「加载示例」熟悉布局;真实配置请先去掉密码、Token、私钥。
- 看状态栏。 输入时会
oninput触发校验:成功显示「YAML 格式正确」;失败显示 js-yaml 的错误信息(含行/列线索时优先按行改缩进)。 - 美化。 点「美化 YAML」:在能
load的前提下,用 2 空格dump到右侧(lineWidth: -1、noRefs: true,避免锚点引用写法干扰阅读)。 - 压缩。 点「压缩 YAML」:以 flow 风格尽量收紧空白,便于对比「解析后结构」而非阅读。
- 转 JSON。 「YAML 转 JSON」输出缩进后的 JSON;再可用 JSON 格式化 做二次整理或压缩。
- JSON 转 YAML。 左侧若是 JSON,点「JSON 转 YAML」;非法 JSON 会在状态栏报
JSON.parse错误。 - 复制与清空。 输入/结果区均可「复制」;「清空」同时清两侧与状态。
能力边界(对照真实页面)
- 支持: 语法校验、美化 dump、flow 压缩、YAML→JSON、JSON→YAML、示例与主题切换。
- 不保证: 保留原注释与原手写风格;多文档一次性完整 round-trip;所有 YAML 1.1 怪异类型在全语言生态一致。
- 安全: 浏览器本地解析;仍不要在不可信环境粘贴生产 Secret 明文。
5. 常见错误与处理办法
| 现象 | 常见原因 | 怎么处理 |
|---|---|---|
mapping values are not allowed here |
某行 : 使用不当、未加引号的字符串里含 : |
给该标量加引号;检查是否少了换行就写了新键 |
bad indentation / 缩进相关 |
Tab、同级不对齐、列表嵌套错位 | 全选后统一转空格;按 2 空格重美化 |
| 状态栏报错但「看起来齐」 | 全角空格、不可见字符、从 Word/网页复制 | 重新用纯文本粘贴;先美化再改业务 |
| 只校验过第一段,后面资源没查到 | 多文档 --- |
分段校验;或用目标 CLI 做权威检查 |
| 美化后注释没了 | dump 基于对象树 | 注释需另存;重要说明放仓库文档 |
yes/on 变成 true |
布尔猜测 | 改成 "yes" 或真正的 true/false |
版本 1.10 变成 1.1 |
浮点解析 | 强制引号字符串 |
| JSON 转 YAML 失败 | 左侧其实是 YAML 或尾逗号 JSON | 确认输入;JSON 先过格式化工具 |
| 压缩后更难读 | flow 风格本就为人机折中的紧凑形 | 压缩只用于体积/管道;阅读请美化 |
锚点 *anchor 行为异常 |
noRefs dump 或解析器差异 |
展开重复块,或固定团队禁用锚点 |
建议排错顺序
- 是否混用 Tab / 全角空白。
- 报错行附近
:、-、引号是否成对。 - 类型猜测是否把字符串吃成布尔/数字。
- 是否多文档只检查了一段。
- 最后才怀疑业务字段名写错。
6. 真实工作场景
场景 A:kubectl apply 被拒,怀疑是缩进
从失败清单中复制相关片段(脱敏),贴进工具。若状态栏直接报错,按行号改;若校验通过,再怀疑 API 版本、必填字段或 RBAC——格式化工具只证明「这是合法 YAML 对象树」,不证明「集群接受该资源」。
场景 B:GitHub Actions 在 with: 下莫名其妙
run: 多行脚本、with: 下的 : 字符串最容易炸。把 job 片段贴入工具校验;对含冒号的消息使用引号或块标量(| / >)。美化后把片段贴回 workflow 文件,避免在网页里改完整仓库密钥。
场景 C:后端给 JSON,运维要 YAML values
左侧贴接口样例 JSON →「JSON 转 YAML」→ 复制到 Helm values 草稿。再人工补注释与环境差异。若 JSON 很大,先在 JSON 格式化 确认合法并压缩字段认知负担。
场景 D:Code Review 里「同逻辑、不同风格」
双方各贴一份 YAML,都美化成 2 空格后再 diff(编辑器或专用 diff)。减少「空格战争」对逻辑审查的干扰。注意:美化会丢注释,review 注释需看原文件。
场景 E:怀疑类型导致的配置「偶发」
同一份配置在 Node 与 Python 服务行为不同。转成 JSON 后看每个叶子的 JSON 类型;对版本号、国家代码、以 0 开头的编号统一加引号,从源头消除猜测。
场景 F:教学「为什么不能从聊天软件直接拷配置」
演示:从富文本拷贝导致的奇怪空白 → 校验失败;纯文本或「加载示例」→ 成功。让新人建立「配置只走代码库与纯文本」的习惯。
7. 编写与协作清单
- 仓库级统一缩进(2 或 4 空格)与「禁止 Tab」
- 提交前对变更的 YAML 做一次解析校验(本地工具或 CI)
- Secret 用密封机制或外部密钥系统,不进明文清单与聊天
- 需要注释说明的,注释写在 YAML;需要程序消费的,另提供 JSON/ schema
- 多文档文件在 README 中说明「一份文件多个资源」
- 对易猜错的标量一律加引号
- 美化后的输出若要回写仓库,过一遍业务 diff,避免无意义大面积重排引发冲突
常见问题
YAML 一定比 JSON 更适合配置吗?
不一定。人读多、要注释、要多文档时 YAML 舒服;机器生成、严格类型、HTTP API 时 JSON 更简单。很多团队「人改 YAML、机器出口 JSON」。
为什么美化后我的锚点或注释没了?
因为美化路径是 load 成对象再 dump。注释不是对象树的一部分;锚点在 noRefs 策略下会展开。需要保留手写风格时,只做校验、不回写 dump 结果,或用支持保留注释的专用 linter 链。
压缩 YAML 和压缩 JSON 一样吗?
不完全一样。本工具压缩偏向 YAML flow 风格;JSON 压缩是去空白的紧凑 JSON。给 HTTP 用通常直接 YAML→JSON 再压 JSON。
多文档文件能一次美化吗?
页面主路径按单次 load/dump 设计。多文档请拆段处理,或依赖 kubectl/CI 的多文档支持做权威验证。不要假设网页工具与集群客户端行为 100% 相同。
Tab 在我编辑器里显示正常,为什么还失败?
显示宽度与解析规则无关。YAML 实现期望空格缩进;把文件转到「显示空白字符」模式常能看到 Tab 标记,再全部转空格。
在线工具会上传我的 K8s Secret 吗?
WebUtils 该页在浏览器内用 js-yaml 处理。仍建议:生产 Secret 不要粘到共享桌面或录屏演示;用完清空;优先本地文件与密封方案。
`null`、`~`、空值有什么区别?
在 YAML 里常被解析为 null,但写回风格可能不同。团队应约定只用一种(例如显式 null),并在 schema 里标明可选字段。
继续浏览
先用「加载示例」走通「粘贴 → 看状态栏 → 美化 → 转 JSON」,再拿真实脱敏片段对照错误表。需要纯 JSON 排错时打开 JSON 格式化;需要桥接转换时打开 JSON↔YAML。