YAML 锚点转 JSON 会怎样?别名展开、合并键和注释要逐项核对
一份 YAML 用 &defaults 定义公共值,再用 *defaults 引用,看起来只写了一次配置。转成 JSON 后,这些引用会变成什么?再转回 YAML,原来的注释和锚点能否回来?宝塔拨测的“YAML/JSON互转”可以用来检查这段转换,但不能把成功输出 JSON 理解为所有 YAML 语义都已按原应用展开。
下面使用公开的虚构测试配置,只观察转换结果,不修改任何服务配置。
别名会展开为 JSON 数据
打开“YAML/JSON互转”,保留“YAML → JSON”方向,输入:
# shared test values
defaults: &defaults
timeout: 30
retries: 2
copy: *defaults
点击“转换为 JSON”。本次右侧 defaults 与 copy 都包含 timeout: 30 和 retries: 2,没有保留 &defaults、*defaults 或开头的注释。

这里 &defaults 是给节点设置锚点,*defaults 是引用该节点的别名。JSON 结果写出了对应的对象内容,方便查看两处最终值;它没有表达两处在 YAML 中引用同一节点的关系。以后只修改 JSON 中的 defaults.timeout,并不意味着 copy.timeout 会自动跟着修改。
因此,转换结果适合拿去给需要普通 JSON 数据的接口或程序使用。若仍打算利用 YAML 的复用写法继续维护配置,应同时保留原始 YAML,不能只存这一份 JSON。
<< 没有在本次工具中执行合并
把输入改成下面的测试。许多配置文件会用这种写法继承默认值,再单独覆盖重试次数:
# test merge, not a production configuration
defaults: &defaults
timeout: 30
retries: 2
service:
<<: *defaults
retries: 5
点击转换后,重点检查 service 的层级。本次输出中的 service 部分如下:
"service": {
"<<": {
"timeout": 30,
"retries": 2
},
"retries": 5
}

可以看到,别名指向的内容被读出了,但它位于名为 << 的普通键下面。timeout 没有成为 service 的直接字段。这份结果不能当成已经得到 service.timeout = 30、service.retries = 5 的平铺配置。
锚点、别名和合并键是不同的功能。<< 的合并写法有自己的规范背景,解析器采用的版本、模式及应用规则会影响处理方式;不能仅凭“支持 YAML”或“基于某解析库”推断当前页面一定执行合并。本次应以右侧实际结构为准。
如果目标程序需要展开后的普通对象,可以先按原应用的规则确认继承值和覆盖值,再在输入中明确写出所需字段。例如此例应在 service 下直接写 timeout: 30、retries: 5,然后重新转换并检查层级。不要为了让结果看起来简洁,直接删除 << 对象而漏掉其中的默认字段。
转回 YAML 不能找回原稿
复制上一步完整 JSON,切换到“JSON → YAML”,粘贴后点击“转换为 YAML”。本次输出没有恢复开头的注释,也没有重新出现原先命名的 &defaults 和 *defaults。<< 仍是一个键,输出中还为它加上了引号。

这是从 JSON 数据重新生成一份 YAML 文本。原注释、锚点名字、缩进习惯和复用意图已经不在 JSON 里,转换器无法凭空还原它们。即使字段值相同,也不要把往返转换后的文件直接覆盖原稿,再期待注释和维护方式保持不变。
正式使用前,至少核对三项:对象层级是否正确,继承字段是否真的落到目标对象,数字与字符串是否符合接收方要求。遇到 << 这样的写法,还要回到实际读取配置的应用验证。转换页面能说明它生成了什么,应用是否认可这份配置,需要由接收方继续确认。