JSON 变成 Markdown 后,字符串还是字符串吗?一次 frontmatter 往返测试

举报
yd_212881929 发表于 2026/10/22 10:00:27 2026/10/22
【摘要】 一次真实的 JSON→Markdown→YAML 往返测试:复现字符串被解析为布尔、空值与数字的问题,讨论类型保留、序列化策略和可复现 Issue 的写法。AI辅助整理,示例已本地验证。

本文由 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

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。