Javascript is required
踩坑避坑发布于 2026-07-28审校于 2026-08-084 分钟阅读

JSON 转 YAML:空格缩进、Tab 与 ScannerError 边界

YAML 用缩进表达层级,Tab 与空格不是可以随意互换的排版字符。一个看似对齐的 Tab 可能触发解析器的 ScannerError 或同类缩进错误;具体错误名称、行列格式和文案取决于解析器。本文聚焦缩进边界,不把某个解析器的错误信息当成 YAML 标准。

JSON to YAMLYAMLIndentationScannerError

一、问题概述:视觉对齐不代表 YAML 层级一致

下面两行在编辑器中可能看起来对齐,但 YAML 缩进需要由解析器按字符计算。Tab 混入 mapping 或 sequence 的缩进位置时,解析器无法确定当前节点属于哪一层。

二、最小复现:Tab 缩进与空格缩进

示例中的 \t 代表真实 Tab 字符;复制到文件时应确认不是两个可见反斜杠。正确版本只使用空格,并保持同一层级的缩进宽度一致。

const invalid = "user:\n\tname: Ada\n";
const valid = "user:\n  name: Ada\n";

console.log(JSON.stringify(invalid)); // "user:\n\tname: Ada\n"
console.log(JSON.stringify(valid)); // "user:\n  name: Ada\n"

三、根因:YAML scanner 必须在缩进上下文中读取字符

解析器先判断当前行的缩进列,再决定它是 mapping、sequence 还是普通标量。Tab 会让列宽解释依赖规则,混合 Tab/space 还可能只在某个嵌套层级失败。错误可能被命名为 ScannerError、YAMLException 或其他解析器专属类型。

四、推荐方案:生成时只输出空格,解析时保留原始错误上下文

JSON→YAML 生成器应固定空格缩进,并在写文件后用目标解析器回读。遇到错误时保留行号、列号和原文片段,但不要把 PyYAML 的 ScannerError 文案硬编码成所有库都相同;不同解析器应通过适配层归一化错误类别。

五、完整代码:在调用 YAML parser 前定位缩进 Tab

下面的预检只报告出现在行首缩进区的 Tab,不替代 YAML parser。它能提前给出行号,最终语法判断仍由项目实际使用的解析器完成。

function indentationTabLines(source: string): number[] {
  return source.split(/\r?\n/).flatMap((line, index) => {
    const match = line.match(/^[ \t]+/);
    return match?.[0].includes("\t") ? [index + 1] : [];
  });
}

const source = "user:\n\tname: Ada\n";
const lines = indentationTabLines(source);
console.log(lines); // [2]

六、常见错误方案

把 Tab 全局替换成固定数量空格可能改变原本的层级,尤其是混合缩进文件;只看编辑器渲染后的对齐也无法确认真实字符;捕获一个固定的 ScannerError 字符串,会让 js-yaml、PyYAML 或其他库的适配失效。

七、边界条件:字符串中的 Tab 与 block scalar

行首缩进 Tab 与 quoted string 或 block scalar 内容中的 Tab 不是同一个问题。预检应只关注缩进区,不能破坏需要保留的字符串内容。|> block scalar 还会按缩进裁剪文本,修复时要保留其相对层级。

八、如何验证 YAML 修复

先检查原始文件的行首字符,再使用目标解析器读取修复后的文本。对 mapping、sequence、空值、引号字符串和 block scalar 做回读断言;记录解析器名称、错误类型和行列信息,避免把一个库的 ScannerError 误报成 YAML 的统一错误。

九、FAQ

问:YAML 标准是否完全禁止所有 Tab?答:至少不能用 Tab 表示缩进;字符串内容中的 Tab 是另一种语义,仍需按解析器规则处理。

问:为什么我的错误叫 ScannerError,别人的叫 YAMLException?答:这是解析器实现的错误类型差异,名称和文案不是跨库统一 API。

问:把 Tab 换成两个空格一定正确吗?答:不一定,必须结合相邻行和 block scalar 的层级重新解析。

十、总结

YAML 缩进错误的关键是实际字符和层级上下文,而不是编辑器中的视觉对齐。生成时使用一致空格,预检行首 Tab,最终交给目标 parser 验证;ScannerError 等名称和错误文案必须注明解析器差异。

来源与延伸阅读

技术审校所依据的规范与权威参考资料。

相关文章

继续阅读

可打开关联的浏览器工具,使用自己的样本验证文中的处理流程。

打开关联工具