FormatArc YAML to JSON 转换工具界面,显示带行号的语法错误信息FormatArc YAML to JSON 转换工具界面,显示带行号的语法错误信息
作者: FormatArc 编辑部发布日期: 2026-09-02更新日期: 2026-09-02

YAML 语法指南:缩进规则、格式规范与错误检查

1 分钟速览 — YAML 写法要点

  • 缩进只用空格,禁止使用 Tab。2 个空格是事实标准。
  • key: value 中冒号后面必须有空格。key:value 会被当作一个字符串。
  • 列表用 - (短横线加空格),映射用 key: value
  • 可能被误判为数字、布尔值、日期的值要加引号:version: "1.0"
  • 想快速检查错误,把内容粘贴到 FormatArc YAML to JSON 转换工具,带行号的错误信息会直接定位问题位置。

YAML 是什么,在哪里会用到

YAML(YAML Ain't Markup Language)是一种人类易读的文本结构化数据格式。它处理的数据模型和 JSON 相同——字符串、数字、布尔值、null、列表、映射——但语法上不用花括号,而是用缩进来表达层级结构。

如果你在做 DevOps 或云原生开发,大概率已经天天和 YAML 打交道:

  • Kubernetes 清单文件、Helm Chart
  • Docker Compose 配置文件
  • GitHub Actions、GitLab CI、CircleCI 工作流
  • Ansible Playbook
  • OpenAPI 规范
  • 静态网站生成器(Hugo、Jekyll、Eleventy)

静态网站生成器的 frontmatter 也常用 YAML 编写,转成 JSON 的完整流程见 Markdown frontmatter 是什么

这篇文章会带你过一遍 YAML 语法中实际会遇到的所有部分,配有具体示例和新手最常踩的坑。刚接触 YAML、想先看概览的话,可以从 YAML 是什么 读起;想直接对比 YAML 和 JSON,可以看 YAML 和 JSON 的区别;想了解转换步骤,参考 YAML 转 JSON 指南

YAML 的三种基本构件

YAML 文件里出现的所有数据,都是以下三种之一:

  • 标量(Scalar)—— 字符串、数字、布尔值、null 等单个值
  • 序列(Sequence)—— 有序列表
  • 映射(Mapping)—— 键值对(即对象或字典)

这三种可以自由嵌套。映射里可以放列表,列表里可以放映射。光靠它们就能表达所有 JSON 兼容的结构。

缩进规则

YAML 用缩进来表达层级结构。必须记住的规则:

  • 只用空格,不能用 Tab 字符。Tab 在大多数解析器中会直接报语法错误。
  • 确定缩进宽度后,整个文件保持一致(通常用 2 个空格)。
  • 同一层级的元素缩进深度必须相同。
  • 没有闭合符号,结构完全由缩进决定。

正确的写法示例:

database:
  host: localhost
  port: 5432
  credentials:
    user: admin
    password: secret

database 是一个映射,包含 hostportcredentialscredentials 又是一个嵌套映射。2 个空格的缩进让你一眼看清整个结构。

键值对(映射)的写法

映射的格式是 key: value,冒号后面必须有一个半角空格。如果写成 key:value 不带空格,它会被当作一个普通字符串,而不是映射。

name: Alice
age: 30
is_admin: true
bio: null

键通常是简单字符串,但加引号后可以包含空格。

"full name": Alice Cooper

值的类型可以是标量、序列、映射——YAML 支持的所有数据类型都行。

列表(序列)的写法

序列在每行开头写 - (短横线加一个半角空格)。

fruits:
  - apple
  - banana
  - cherry

列表里可以嵌套映射。

users:
  - name: Alice
    role: admin
  - name: Bob
    role: editor

每个短横线标志一个新列表项的开始,到下一个短横线出现之前的内容都属于该项。

块样式与流样式

前面展示的全是块样式(Block style):一行一个条目,用缩进表示嵌套。YAML 也支持类似 JSON 的内联流样式(Flow style)。

fruits: [apple, banana, cherry]
users: [{name: Alice, role: admin}, {name: Bob, role: editor}]

流样式在写短列表时很方便,但数据一多可读性就急剧下降。实际文件中建议默认用块样式。流样式中忘了闭合 [ 会导致不同解析器报不同错误(详见后文解析器错误对照表)。

字符串与引号:什么时候必须加

YAML 中大多数字符串可以不加引号直接写。

greeting: Hello, world

以下情况必须加引号:

  • 值可能被误判为其他类型:version: "1.0"country: "NO"postal_code: "07030"
  • 值以 YAML 结构字符开头:[]{},*|>%@`"'#&!。开头的 -:? 只在后面紧跟空格时才有问题
  • 值中包含冒号加空格(: ),会被误判为映射
  • 想使用 \n\t 等转义序列

单引号(')和双引号(")都可以用。双引号会解析转义序列,单引号则原样保留字面值。

escaped: "line1\nline2"
literal: 'line1\nline2'

实际会造成问题的字符分成两组,组别决定了是否需要引号。下表是本站转换工具使用的解析器(yaml (eemeli) 2.8.3,YAML.parse 默认配置)的行为(2026-08-15 实测,复现脚本在仓库 scripts/benchmarks/yaml-quote-requirements/ 中)。中间列写"安全"的话,只要该字符不在值的最前面,就可以不加引号。

字符放在值最前面时放在值中间时单引号是否够用双引号
[ ] { } ,解析错误安全够用可用
*解析错误(被当作别名)安全够用可用
&不报错,被当作锚点,值丢失安全够用可用
!不报错,被当作标签安全够用可用
#不报错,整个值被当作注释变成 null前面没空格就安全够用可用
| >解析错误(被当作块标量)安全够用可用
% @ `解析错误(保留字符)安全够用可用
- ?单独安全,后面接空格则报错安全够用可用
:单独安全,后面接空格则报错后面接空格则无论位置都报错够用可用
"解析错误安全够用需要 \" 转义
'解析错误安全不够,需写成 ''推荐用这个

从这张表可以得出两个结论。第一,值中间真正危险的只有 : #,所以 url: http://example.com/a,b 不加引号也完全安全。其余都是"开头字符"问题。第二,单引号除了引号字符本身以外几乎能安全包裹所有情况。这就是为什么粘贴 Windows 路径或正则表达式时单引号更安全。只有当你需要 \n\t 被解析为真正的换行或制表符时,才用双引号。

模板语法 {{ }} 写在值开头会炸

Helm 模板或 Ansible 变量展开如果没有渲染就直接丢给 YAML 解析器,开头的 { 会触发特殊字符陷阱。

# 未渲染的 Helm 模板
image: {{ .Values.image }}

{{ 会被解析为两层嵌套的流映射。而且不同解析器的失败方式不同。实测(2026-07-12,复现脚本在仓库 scripts/benchmarks/yaml-syntax-errors/ 中)表明 PyYAML 和 ruamel.yaml 会报 found unhashable key 错误,但 js-yaml 和 eemeli/yaml 完全不报错,悄悄返回 {"image": {"[object Object]": null}} 这样的损坏对象。不报错意味着问题要到了流水线后段才会暴露,这才是最棘手的部分。

解决办法有两个:把整个值加引号让它变成字符串(image: "{{ .Values.image }}"),或者只在模板渲染完成之后才校验 YAML。另外 GitHub Actions 的 ${{ }}$ 开头,不会被解析为流映射,不存在这个问题。

多行字符串

长文本块有两种写法。

字面量块 | 保留源代码中的换行原样。

description: |
  这是第一行。
  这是第二行。

  空行后的第四行。

折叠标量(Folded scalar)> 把换行折叠为空格,适合在源码中折行书写长段落。

paragraph: >
  这段长文字在源码中
  分成了多行书写,
  YAML 会把它合并为一行。

Chomp 指示符:strip / clip / keep

YAML 的块标量有一个 chomp 指示符,决定尾部换行如何处理。指示符紧跟在 |> 后面。

指示符行为示例
(无)— clip保留最后一个换行。默认行为。|
- — strip去掉所有尾部换行。|- >-
+ — keep保留所有尾部空行。|+ >+
clip: |
  line one
  line two
strip: |-
  line one
  line two
keep: |+
  line one
  line two

折叠形式(>>->+)同样适用这三种模式。|- 适合把 YAML 嵌入 JSON 或环境变量时不想有尾部换行的场景。|+ 适合生成 Shell 脚本时尾部空行有意义的情况。

类型与解析器类型推断

YAML 会对不加引号的值做自动类型推断。同一个字面量,根据解析器实现的 YAML 版本和使用的 schema,可能被解析为整数、浮点数、日期或字符串。

integer: 42
hex: 0xFF              # 255(整数,十六进制)
octal: 0o17            # 15(整数,八进制,YAML 1.2)
octal_legacy: 0644     # 420(整数,八进制,YAML 1.1)— 文件权限陷阱
float: 3.14
negative: -7
exponential: 1e3       # 1000.0(浮点数,指数表示)
infinity: .inf         # +Infinity(浮点数)
negative_infinity: -.inf
not_a_number: .nan     # NaN(浮点数)
boolean_true: true
boolean_false: false
null_value: null
tilde_null: ~
date: 2026-04-13
timestamp: 2026-04-13T09:30:00Z

这些值加引号后都可以固定为字符串。

version_string: "1.0"    # 不是数字 1.0
zip_code: "07030"        # 不是数字 7030
file_mode: "0644"        # 不是八进制整数

下表汇总了不加引号的字面量在现代 YAML 1.2 Core schema 加载器(PyYAML、js-yaml、SnakeYAML 默认)和 YAML 1.1 加载器(旧版 PyYAML、Symfony YAML)中分别变成什么。大多数意外行为就藏在这两列的差距里。

字面量YAML 1.2 CoreYAML 1.1注意事项
42integer (42)integer (42)
0xFFinteger (255)integer (255)十六进制解析是规格定义的行为
0o17integer (15)(不识别)仅 YAML 1.2
0644integer (644)integer (420, 八进制)文件权限解析因版本而异
1e3float (1000.0)float (1000.0)部分工具显示时会去掉 .0
.inf / -.inffloat (±Infinity)float (±Infinity)无法序列化为 JSON
.nanfloat (NaN)float (NaN)无法序列化为 JSON
2026-04-13stringdate(日期对象)JSON 与 YAML 往返转换时类型会变
2026-04-13T09:30Zstringtimestamp同上
true / falsebooleanboolean
yes / no / on / offstringboolean"Norway problem"
NOstringboolean (false)下节详述
~ / null / Null / NULLnullnull大小写均为 null
1.0float (1.0)float (1.0)部分工具会重新序列化为 1

如果你的解析器接近生产环境,最右边一列的所有项都应视为潜在 bug。最快的确认方式是拿一个有代表性的文件粘贴到 FormatArc 的 YAML to JSON 转换工具,看 JSON 输出:"NO" 还是 false"2026-04-13" 还是 ISO 日期字符串,一目了然。

两列产生差异的原因是 YAML 1.1 和 YAML 1.2 对类型推断的定义不同。YAML 1.1 包含了一组宽泛的隐式类型标签——包括时间戳、六十进制数、以及引发 Norway problem 的大量布尔词汇。YAML 1.2 用更严格的 Core schema在新标签页中打开 替代了它。Core schema 将布尔值限定为 truefalse(规格中的 Core 正则表达式也接受首字母大写或全大写的 True/TRUE/False/FALSE,但不再接受 yes/no/on/off),废除了隐式时间戳和六十进制标签,其余部分直接跟随 JSON 的值类型。完整的正则表达式规则集见 YAML 1.2.2 规格在新标签页中打开。当两个工具对不加引号的值产生分歧时,原因几乎总是一个实现了 1.1 规则,另一个实现了 1.2 Core schema。

Norway problem — NO 变成 false 的陷阱

YAML 中最著名的陷阱就是"Norway problem"。YAML 1.1 解析器(PyYAML、Symfony YAML、旧版 SnakeYAML 等,目前仍广泛使用)会把不加引号的 NO 解析为布尔值 false。如果你这样写国家代码列表:

countries:
  - DE
  - FR
  - NO
  - SE

解析的瞬间就变成了 ["DE", "FR", false, "SE"]YESONOFFYN 以及各种大小写变体,根据解析器不同都会触发同样的问题。

解决办法是把可能被误判的值加引号。

countries:
  - "DE"
  - "FR"
  - "NO"
  - "SE"

YAML 1.2 虽然把布尔值限定为 true / false,但大量生产工具仍内置 1.1 的加载器。国家代码、语言代码、版本字符串、短标识符,全部加引号才安全。

严格的新版布尔集合定义在 YAML 1.2.2 规格在新标签页中打开 中,旧版工具仍在实现的规则见 YAML 1.1 规格在新标签页中打开

注释

注释从 # 开始到行尾结束。可以独占一行,也可以写在值后面。

# 上游请求的最大重试次数
retries: 3  # 再高就会超过上游超时

注释是 YAML 相比 JSON 在配置文件场景下最大的优势之一。用它来说明"为什么设这个值",而不是"这是什么"。转成 JSON 后所有注释都会消失,所以 YAML 文件本身才是可信源。如果非要在 JSON 里写注释,JSON 可以注释吗 介绍了 JSONC / JSON5 等 4 种替代方案。

锚点与别名:复用定义

YAML 用 & 定义锚点(Anchor),用 * 引用别名(Alias)。<<: 合并键(Merge key)可以把一个映射作为默认值引入。

defaults: &defaults
  adapter: postgres
  host: db.internal
  pool: 5

development:
  <<: *defaults
  database: myapp_dev

production:
  <<: *defaults
  database: myapp_prod
  pool: 20

production 继承了 defaults 的配置,只覆盖了 pool 的值。这是在不复制粘贴的情况下共享环境配置的干净写法。

合并键(<<:)共享配置

<<: 合并键是锚点最实用的搭档。它把一个映射的键引入另一个映射,让你可以表达"和那个一样,只是这里改一下",不用反复复制。Docker Compose、GitLab CI、Rails 的 database.yml 中都大量使用这种模式。

base: &base
  image: node:20
  restart: unless-stopped
  environment:
    NODE_ENV: production

services:
  api:
    <<: *base
    command: npm run start:api
  worker:
    <<: *base
    command: npm run start:worker
    environment:
      NODE_ENV: production
      WORKER_QUEUE: high

使用时有两个注意点:

  • 合并键只做一层(浅合并)。嵌套映射(如上例中的 environment)不会被深度合并,而是整体替换。
  • 合并键是 YAML 1.1 的特性。严格的 YAML 1.2 解析器可能忽略它,但 Docker Compose 和 GitLab 仍然支持 1.1 语义,所以正常使用没问题。

schema 与标签:YAML 如何决定类型

YAML 1.2 定义了三种控制不加引号的字面量如何解释的 schema。

  • FailSafe — 只支持字符串、映射、序列。最安全的 schema,其他一切字面量都变成字符串。很少作为默认。
  • JSON — 支持 JSON 兼容类型(字符串、整数、浮点数、布尔值、null、映射、序列),与 JSON.parse 的结果一致。
  • Core — 通常的默认值。在上面表格的类型推断规则基础上增加了十六进制、八进制、.inf.nan~ 的支持。

大多数解析器默认使用 Core(PyYAML 的 safe_load、js-yaml 的默认值、SnakeYAML 的 SafeConstructor)。Symfony YAML 仍然默认使用 YAML 1.1 语义。JSON schema 覆盖的数据类型与嵌套结构,完整说明见 JSON 语法完全指南

当 schema 推断和你想要的不一致时——比如你想让 version: 1.0 保持字符串但被解析为浮点数——可以用显式标签强制类型。

version: !!str 1.0       # 强制为字符串 "1.0"
count: !!int "42"        # 即使加了引号也强制为整数 42
empty: !!null ""         # 不是空字符串,而是显式的 null

!! 前缀表示"使用默认标签库中的标准标签"。自定义标签用单个 !(比如 CloudFormation 模板中的 !Ref),需要解析器专门支持。应用层面的 YAML 文件通常只需要知道 !!str 就够了。

多文档文件

一个 YAML 文件可以包含多个独立文档,用 --- 独占一行作为分隔。

---
kind: Service
name: web
---
kind: Deployment
name: web
replicas: 3

Kubernetes 中把多个清单合并到一个文件时就是这种形式。JSON 没有等价结构,转换时需要选择其中一个文档或者用外层数组包裹。

锚点、合并键、多文档的兼容性实测

锚点、合并键、多文档在 YAML 语法上都合法,但能不能用完全取决于你把它放在哪个环境里。4 种解析器和 Docker Compose 经过直接实测(2026-07-12,复现脚本在仓库 scripts/benchmarks/yaml-tool-acceptance/ 中),托管服务查阅了官方文档。

环境锚点 & *合并键 <<:多文档 ---
js-yaml支持(实测)支持(实测)load 报错。loadAll 支持(实测)
PyYAML支持(实测)支持(实测)safe_load 报错。safe_load_all 支持(实测)
yaml (eemeli)(FormatArc 转换工具使用的解析器)支持(实测)默认不展开,<< 作为字面键保留(实测)parse 报错。parseAllDocuments 支持(实测)
Docker Compose v5.3.0支持(实测)支持(实测)多个文档合并为一个配置后接受(实测)
GitHub Actions2025-09-18 起支持在新标签页中打开不支持 — 使用会报语法错误在新标签页中打开官方文档未提及
GitLab CI支持在新标签页中打开支持在新标签页中打开官方文档未提及
Kubernetes (kubectl)官方文档未明确说明官方文档未明确说明支持在新标签页中打开

这张表有三个重点:

  • GitHub Actions 支持锚点但不支持合并键。 2025 年 9 月锚点支持上线后,<<: 仍然报语法错误,所以从 GitLab CI 直接复制工作流会出问题。
  • eemeli/yaml 默认遵循 YAML 1.2,而合并键是 YAML 1.1 的特性,所以它不会展开 <<:。解析不会报错,但 {"<<": {...}} 这个键会原样保留,变成隐蔽的 bug。
  • 多文档取决于你调用哪个 API。 4 种解析器在单文档加载 API 下都会报错,切换到多文档专用 API 后就能正常处理。

实际场景中的 YAML 写法

不管你是写 5 行配置还是生产环境的部署清单,适用的语法规则是一样的。以下是 2026 年开发中最常见的 3 个场景。

Kubernetes Deployment 清单

最简的 Deployment 也同时涉及映射、序列、多行字符串和布尔值。spec.template.spec.containers 附近的缩进错位是最典型的失败原因。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
          env:
            - name: FEATURE_FLAG_NEW_HEADER
              value: "true"      # 故意加引号 — 裸的 true 会被当作布尔值
          resources:
            limits:
              cpu: "500m"
              memory: 256Mi

value: "true" 的引号是关键。去掉引号的话,Kubernetes 会接受布尔值,容器里拿到的可能是 True(Python 风格)或者直接启动失败。

GitHub Actions 工作流

GitHub Actions 工作流是深度嵌套的映射,run 块中多行 Shell 脚本很常见。|(字面量)和 >(折叠)的区分在这里特别有用。

name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"      # 加引号保留末尾的 0
      - name: Install
        run: npm ci
      - name: Test
        run: |
          npm run lint
          npm run build
          npm test -- --run

这里最常犯的错误是去掉 node-version: "20" 的引号。YAML 会把它转成整数 20,某些版本的 setup-node 可能不接受。凡是"看起来像数字但必须是字符串"的值,都要加引号。

Docker Compose 服务定义

Compose 文件是映射、序列、环境变量字典、绑定挂载字符串混合的短 YAML,适合练习识别缩进问题。

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"               # 加引号避免被解析为六十进制数
    environment:
      NGINX_HOST: example.com
      NGINX_PORT: "80"          # 必须加引号:环境变量值必须是字符串
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api
  api:
    build: ./api
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 5s
      retries: 3

两个陷阱:"8080:80" 不加引号的话 YAML 1.1 解析器可能把它当六十进制数读;environment: 下的值最终要以字符串形式传递,加引号更安全。

常见错误与各解析器的报错信息对比(实测)

以下是几乎每个开发者都会踩的 YAML 坑。

  • 用 Tab 字符做缩进 — 肉眼看不见的 Tab 混入后极难定位
  • 冒号后面没空格 — key:value 被当作一个字符串
  • 缩进不一致 — 同一层级的元素必须缩进相同
  • 不加引号的 NOOFFYESON 被解析为布尔值(Norway problem)
  • 不加引号的值里包含冒号 — time: 10:30 可能被解析为六十进制数
  • 块样式和流样式混用 — 解析器会困惑
  • 同一映射中键重复 — 行为因实现而异

搜索这些错误时最麻烦的是:同一个错误在不同解析器中报完全不同的信息。下面把 6 种典型错误分别喂给 js-yaml、yaml (eemeli)、PyYAML,记录了实际输出的错误文本(2026-07-12 实测,含 ruamel.yaml 在内的 4 种解析器原始日志和复现脚本在仓库 scripts/benchmarks/yaml-syntax-errors/ 中)。

错误js-yaml 报错yaml (eemeli) 报错PyYAML 报错
用 Tab 缩进tab characters must not be used in indentation(第 2 行)Tabs are not allowed as indentation(第 2 行)found character '\t' that cannot start any token(第 2 行)
缩进不一致(2 和 3 空格混用)bad indentation of a mapping entry(第 3 行)Nested mappings are not allowed in compact mappings(第 2 行)mapping values are not allowed here(第 3 行)
值中未加引号的 : url: http://x.com: 8080bad indentation of a mapping entry(第 1 行第 24 列)Nested mappings are not allowed in compact mappings(第 1 行第 6 列)mapping values are not allowed here(第 1 行第 24 列)
双引号未闭合unexpected end of the stream within a double quoted scalar(末行)Missing closing "quote(第 2 行第 8 列)while scanning a quoted scalar ... found unexpected end of stream(指向起始引号位置)
未定义锚点的 *aliasunidentified alias "missing"Unresolved alias (the anchor must be set before the alias): missing(不报行号)found undefined alias 'missing'
流式 [ 未闭合missed comma between flow collection entries(下一行)Flow sequence in block collection must be sufficiently indented and end with a ](第 2 行)while parsing a flow sequence ... expected ',' or ']'

读这些错误的 3 个技巧。第一,PyYAML 的 mapping values are not allowed here 和 js-yaml 的 bad indentation of a mapping entry 看起来不相关,但它们指向同一个原因:在不能开始映射的位置出现了 : 。eemeli 的 Nested mappings are not allowed in compact mappings 是第三种说法。第二,不同解析器报告的行号不同:引号未闭合时 js-yaml 指向文件末尾,PyYAML 指向起始引号位置,所以要同时看报错行前后和引号起始位置。第三,eemeli 有时比 js-yaml 早报一行,因为它报告的是紧凑映射开始的位置而非出错的位置。

定位这类错误最快的办法是让解析器来读。不用安装任何东西,把 YAML 粘贴到 FormatArc 的 YAML to JSON 转换工具即可。合法的 YAML 会立即显示 JSON 结果,不合法则会提示语法错误并给出需要检查的行号。

"It is forbidden to specify block composed value at the same line as key" 错误解决

这个错误是 JetBrains/IntelliJ 系列 IDE(IntelliJ IDEA、PyCharm、GoLand、Rider、DataGrip)的 YAML 检查器(Inspection)输出的信息。原文定义在 YAMLBundle.properties在新标签页中打开 中的 annotator.same.line.composed.value.message

意思只有一个:块集合(block collection)的起始和键在同一行上。查看检查器源码在新标签页中打开,它只检查两种形态——块序列的第一个元素和键在同一行,或块映射的第一个键值对和键在同一行。其他情况不会触发。

形态 1:块序列从键所在行开始。

# 触发 Inspection 的写法
key: - item1
     - item2

修复:把第一个元素换到下一行。

key:
  - item1
  - item2

形态 2:块映射从键所在行开始。

# 触发 Inspection 的写法
key: sub: value
     sub2: value2

修复:在冒号后换行。

key:
  sub: value
  sub2: value2

两种形态都是 YAML 规格上真正的语法错误,不是 IDE 的偏好问题。解析器同样会拒绝:yaml 包对形态 1 返回 Unexpected block-seq-ind on same line with key,对形态 2 返回 Nested mappings are not allowed in compact mappings

这和重复键检查是不同的错误。 映射中键重复时,IDE 会报 Key 'x' is duplicated(同 bundle 中的 YAMLDuplicatedKeysInspection.duplicated.key)。如果提示键重复了,需要改键名或拆分父节点,和块集合的位置无关。

Helm 或 Jinja 模板中误报的情况: 检查器在设计上遇到模板语言注入的元素时会提前终止检查,所以正确编写的模板本不该被标记。如果仍然报错,那是已知的误报(如 IJPL-64437在新标签页中打开),文件本身不需要修改。

修复后粘贴到 FormatArc 的 YAML to JSON 工具确认块集合是否已正确换行。转换完全在浏览器内完成,你的数据不会上传到任何地方。

用 FormatArc 在浏览器中校验 YAML

FormatArc 的纯浏览器工具可以直接当作简易 YAML 校验器使用。

FormatArc YAML to JSON 转换工具界面,显示带行号的语法错误信息FormatArc YAML to JSON 转换工具界面,显示带行号的语法错误信息

  • YAML to JSON — 粘贴 YAML 获取 JSON 输出,出错时显示行号

所有处理都在浏览器本地完成。内部配置文件或包含密钥的数据可以放心粘贴调试,数据不会离开你的机器。

常见问题

YAML 缩进可以用 Tab 吗?

不行。YAML 规格只允许空格,Tab 字符在大多数解析器中会直接报语法错误。编辑 .yml.yaml 文件时,把编辑器的 Tab 键设置为插入 2 个空格。

.yml.yaml 有什么区别?

没有区别。两种扩展名在所有 YAML 解析器中的处理方式完全相同。官方规格推荐 .yaml,但 .yml 也很常见,完全没问题。

字符串必须加引号吗?

不需要。YAML 中大多数字符串可以直接写。只有当值会被误判为其他类型,或以 -:[{|> 等特殊字符开头时,才需要加引号。

写了 version: 1.0 结果变成了 1,为什么?

YAML 把 1.0 解析为浮点数,部分序列化工具会把它输出为 1。想保持字符串形式就加引号:version: "1.0"

缩进用几个空格合适?

2 个空格是惯例。Kubernetes、Docker Compose、GitHub Actions 等大多数官方示例都用 2 个空格。4 个空格也没问题,只要单个文件内保持一致就行。

不装任何东西怎么校验 YAML?

把文件内容粘贴到 FormatArc 的 YAML to JSON 转换工具即可。合法的 YAML 会立即输出 JSON,不合法则显示带行号的错误信息。

一个文件里能写多个 YAML 文档吗?

可以。用 --- 独占一行作为分隔符。Kubernetes 把多个清单打包到一个文件时就是标准做法。一个文件里可以放任意多个文档。

总结

  • YAML 用缩进而非花括号表达结构
  • 缩进只用空格,保持文件内一致
  • 字符串只在会被误判时才加引号
  • 注释、多行字符串、锚点能大幅提升配置文件的可读性和复用性
  • 校验 YAML 语法最快的方式:粘贴到 FormatArc 的 YAML to JSON 工具即可