Files
hermes-skills/skills/legal/contract-reviewer/references/yaml-frontmatter-issues-json-pitfall.md
T

2.1 KiB

YAML Frontmatter issues_json 嵌入陷阱(2026-06-26)

问题

Reviewer 输出 YAML frontmatter 时,issues_json 字段需要包含一个 JSON 数组字符串。如果直接写成:

issues_json: [{"id":"R1-001",...}]

YAML 解析器会将 [{...}] 解析为 YAML 原生列表(因为 YAML 是 JSON 的超集),而不是字符串。下游 workflow 取到的 issues_json 类型是 list 而非 str,导致 json.loads() 失败。

根因

YAML 1.2 规范明确:YAML 是 JSON 的严格超集。任何合法的 JSON 也是合法的 YAML,且会被解析为对应的原生类型(对象→mapping,数组→sequence),而非字符串。

解决方案

方案一:YAML literal block scalar(|)语法

issues_json: |
  [{"id":"R1-001","severity":"critical",...}]
  • | 告诉 YAML 解析器将后续缩进内容视为字面字符串
  • 字符串末尾会自动去除尾随换行
  • JSON 内容不受 YAML 类型推断影响

方案二:单行引号字符串(降级方案)

当 workflow 引擎对 literal block scalar 解析不兼容时,使用单行转义字符串:

issues_json: "[{\"id\": \"R3-001\", \"severity\": \"major\", ...}]"
  • 用 Python json.dumps(issues, ensure_ascii=False) 生成 JSON 字符串
  • 直接拼接到 YAML 行中:issues_json: "{json_str}"
  • YAML 双引号字符串内,JSON 的双引号 \" 会被正确解析

方案三:Python 生成(最可靠)

import json
issues_json = json.dumps(issues, ensure_ascii=False)
yaml_line = f'issues_json: "{issues_json}"'

验证

写入后必须验证 YAML 往返:

import yaml, json
parsed = yaml.safe_load(yaml_str)
assert isinstance(parsed['issues_json'], str), f"Expected str, got {type(parsed['issues_json'])}"
reparsed = json.loads(parsed['issues_json'])
assert len(reparsed) == expected_count

其他注意事项

  • converted_filename 为空时写 ''(两个单引号),不要省略
  • 不要在 frontmatter 中添加 schema 未定义的字段
  • 所有中文字段值无需转义,allow_unicode=True 即可