js-yaml 3.10.0加载YAML 1.2锚点报错:无法合并映射
解决js-yaml 3.10.0加载YAML锚点数组时的合并错误
我刚好踩过这个坑,咱们一步步拆解问题、解决问题:
问题重现
先还原下你的场景,YAML文件写法大概是这样:
defaultEd: &defaultEd - "高中" - "本科" user: name: "张三" education: <<: *defaultEd
对应的Node.js加载代码:
const yaml = require('js-yaml'); const fs = require('fs'); try { const doc = yaml.safeLoad(fs.readFileSync('someTest.yml', 'utf8')); console.log(doc); } catch (e) { console.error(e.message); }
报错详情
运行后会精准抛出这个错误:
cannot merge mappings; the provided source object is unacceptable
如果someTest.yml文件不存在,还会额外收到提示:
Error: ENOENT: no such file or directory, open 'someTest.yml'
原因分析
js-yaml 3.x版本里,<<这个合并操作符只支持处理映射(键值对结构),完全不兼容数组类型的锚点。当你用<<:*defaultEd去引用数组锚点时,库会强行把数组当作映射来解析合并,自然就触发了类型不匹配的错误。
解决方案
根据你想要education直接继承锚点数组内容的需求,最简单的修改就是去掉<<:,直接引用锚点:
修改后的YAML文件:
defaultEd: &defaultEd - "高中" - "本科" user: name: "张三" education: *defaultEd
重新运行代码,就能得到你期望的输出:
{ user: { name: '张三', education: [ '高中', '本科' ] } }
如果之后需要在这个数组基础上追加元素,更稳妥的方式是直接扩展:
defaultEd: &defaultEd - "高中" - "本科" user: name: "张三" education: - "高中" - "本科" - "硕士"
或者在Node.js代码里动态合并:
const doc = yaml.safeLoad(fs.readFileSync('someTest.yml', 'utf8')); doc.user.education = [...doc.defaultEd, "硕士"];
关于文件不存在的处理
如果遇到“someTest.yml文件不存在”的提示,检查这两点:
- 确认文件在当前Node.js进程的工作目录下(可以用
console.log(process.cwd())查看当前路径) - 改用绝对路径读取文件更稳妥,比如:
const path = require('path'); const filePath = path.resolve(__dirname, 'someTest.yml'); // __dirname是当前脚本所在目录 const doc = yaml.safeLoad(fs.readFileSync(filePath, 'utf8'));
内容的提问来源于stack exchange,提问作者leeand00
相关产品推荐
相关产品推荐

