JSON 变成 Markdown 后,字符串还是字符串吗?一次 frontmatter 往返测试
本文由 AI 辅助整理,命令和示例均经过本地实际执行。讨论对象为 workvault 的 main 提交
085fcde1bff20b1a4dc132d76bf8d82f7efa6bee,用于记录数据转换的测试方法,不代表后续版本仍有相同行为。
将 JSON 资料批量转换成 Markdown,看上去只要把字段写进 frontmatter 就完成了。但“生成成功”与“数据含义没有变化”之间,还有一次容易遗漏的验收:把生成结果重新读回来,比较字段的值和类型。
这次我用一条普通记录做了测试,没有分组,没有重复文件名,也没有调用大模型接口。CLI 返回写入成功,文件也确实存在;问题出现在 YAML 解析阶段。
一条记录就能复现
测试输入包含几组外观相近、类型不同的数据:
[{"id":"item-1","flag":"true","empty":"","null_text":"null","code":"001","date":"2026-10-22","label":"ordinary","number":42,"bool":true}]
这里的 flag 是四个字符组成的字符串,bool 才是真正的布尔值;null_text 是文本,空字符串也不等于空值。code 可以代表业务编号,前导零有意义。
配置文件指定文件名字段与需要进入 frontmatter 的字段:
{"name":"yaml-string","outputDir":"notes","filenameTemplate":"{{record.id}}","template":"# Record","frontmatter":["id","flag","empty","null_text","code","date","label","number","bool"]}
在 Node.js v24.18.1 环境安装依赖、构建 CLI 后运行:
node cli.js run --vault ./repro-vault --profile ./profile.json --data ./data.json
退出码为 0,命令报告“已写入 1 篇,跳过 0 篇,错误 0”。这说明运行流程成功,却还不能证明字段被完整保留。
看起来正确的输出,为什么会改变类型
生成文件中的片段是:
flag: true
empty:
null_text: null
code: 001
date: 2026-10-22
number: 42
bool: true
我将两个 --- 分隔符之间的内容交给 Python 的 yaml.safe_load,实际读到:flag 变成布尔值,empty 与 null_text 都变成 None,code 变成整数 1,日期字符串被解析成日期对象。普通文本、原本的数字和布尔值则正常。
这些结果需要区分解析器和 schema。日期及某些数字写法在不同 YAML 实现之间存在差异,不能直接断言所有工具都会得到同一种类型。但未加引号的 true、null、空标量已足以说明:输出格式允许解析器作出与 JSON 输入不同的解释。
如果后续系统按字符串编号关联数据,"001" 与 1 不是同一个标识;如果筛选逻辑区分“用户主动填写空文本”和“没有值”,空串变空值也会影响判断。问题发生时没有异常堆栈,很容易被“文件生成成功”的验收掩盖。
测试应绕一圈,而不只检查冒号
一种有效测试路径是:构造已知类型的 JSON,调用真实生成流程,提取 frontmatter,用下游兼容的 YAML 解析器读取,再比较值及类型。测试矩阵可以包含:
- 普通文本、空字符串、首尾空格、冒号与换行;
- 文本形式的布尔值、空值、数字、前导零编号;
- 日期外观文本,以及真实数字、布尔值、null;
- 数组与嵌套对象,以及带特殊字符的字段名。
对于“必须保留字符串”的字段,应同时断言类型与具体内容。例如不能仅比较打印结果,因为日期对象与日期字符串可能显示得一样;也不能把所有值转成字符串后比较,否则又会掩盖原本的类型差异。
这类测试属于数据边界验证。只检查 frontmatter 是否有分隔符、每一行是否包含冒号,可以帮助发现格式错误,却无法保证语义正确。
一个更保守的序列化选择
在数据来源明确是 JSON 的场景,可以对字段名和所有字符串始终使用可靠的双引号转义;真实数字、布尔值、null 保留实际类型。JSON 的双引号字符串写法可用于 YAML,但这不意味着整个模板可以随意拼接:换行、控制字符、嵌套结构和字段名仍应交给可靠序列化过程处理,并用目标解析器验证。
示例应明确表达差异:
"flag": "true"
"empty": ""
"null_text": "null"
"code": "001"
"number": 42
"bool": true
如果项目已有成熟的 YAML 序列化依赖,优先使用其类型规则,避免维护一长串容易遗漏的正则条件。若采用更小的自定义实现,就要限定输入范围,并用往返测试守住承诺。
把问题报告写得可验证
我将本次复现整理成独立 Issue,记录了精确提交、运行环境、输入、配置、CLI 返回和解析后的差异。报告聚焦单条记录的类型保留,不混入文件名碰撞、分组映射等其他问题,便于维护者直接复现和评估。
这个过程带来的主要收获是:数据转换的终点不是“文件落盘”,而是“下一位消费者按预期读到了相同的数据”。对 JSON、CSV、YAML、Markdown 等格式互转工具,这条验收原则同样适用。
参考源码:https://gitcode.com/agent-best-practices/workvault
本次问题报告:https://gitcode.com/agent-best-practices/workvault/issues/50
- 点赞
- 收藏
- 关注作者
评论(0)