拓冰建站拓冰建站
首页 / 资讯中心 / 正文

chezmoi 模板函数 fromJsonc 详解:在 dotfiles 模板中解析带注释的 JSONC 数据

chezmoi 模板函数 fromJsonc 详解在 dotfiles 模板中解析带注释的 JSONC 数据【免费下载链接】chezmoiManage your dotfiles across multiple diverse machines, securely.项目地址: https://gitcode.com/gh_mirrors/ch/chezmoifromJsonc是 chezmoi 模板引擎中用于将 JSONCHuman JSON即带注释与尾随逗号的 JSON 超集文本解析为结构化数据的模板函数。它让模板作者可以直接读取带有注释、尾随逗号等人类友好写法的配置文件与数据源并像使用普通 map/slice 一样访问其中的字段。读完本文你将掌握fromJsonc的完整签名、底层解析原理、数字类型转换规则、实际模板用法及其在 chezmoi 代码库内部的真实应用场景。函数签名与核心语义根据官方函数参考文档 fromJsonc.mdfromJsonc的签名定义如下fromJsonc jsonctext参数jsonctext一个字符串内容是待解析的 JSONC 文本。返回值解析得到的值对象、数组、字符串、数字或布尔值。解析引擎底层使用github.com/tailscale/hujson库完成 JSONC 解析该依赖在 go.mod 中声明。简单来说fromJsonc与模板函数fromJson行为一致但额外兼容 JSONC 语法扩展允许//行注释、/* ... */块注释以及对象与数组末尾的尾随逗号trailing comma这正是诸如 VS Code、微软 WinGet 等工具配置文件所采用的Human JSON风格。JSONC 与标准 JSON 的区别标准 JSONRFC 7159是严格的纯数据格式不允许任何注释和尾随逗号而 JSONCJSON with Comments是它的超集允许//单行注释/* ... */多行块注释数组和对象最后一个元素之后的逗号尾随逗号。例如下面这份文本是合法的 JSONC但无法被标准 JSON 解析器接受{ key: 1, // Comment }该示例正是 chezmoi 测试套件中用于验证fromJsonc的输入数据见 templatefuncs.txtar。底层实现原理模板函数入口fromJsonc的模板函数实现位于 templatefuncs.go// fromJsoncTemplateFunc parses s as JSONC and returns the result. In contrast // to encoding/json, numbers are represented as int64s or float64s if possible. func (c *Config) fromJsoncTemplateFunc(s string) any { var value any must(chezmoi.FormatJSONC.Unmarshal([]byte(s), value)) return value }实现非常简洁将输入字符串转为字节切片交给 chezmoi 内部定义的FormatJSONC反序列化器结果存入any类型变量返回。解析失败时通过must抛出 panic与 chezmoi 其他模板函数如fromJson、fromYaml的错误处理风格保持一致。函数注册fromJsonc在模板函数注册表中与众多内建函数一起注册见 config.gofromJsonc: c.fromJsoncTemplateFunc,因此它可以在任何 chezmoi 模板上下文中直接使用包括chezmoi execute-template、源文件模板、chezmoi data输出等。文档站点配置 mkdocs.yml 也将其注册为独立的参考页面。JSONC 反序列化的两步流水线FormatJSONC由 format.go 中的formatJSONC类型实现其Unmarshal采用先标准化、再按 JSON 解析的两步策略// Unmarshal implements Format.Unmarshal. func (formatJSONC) Unmarshal(data []byte, value any) error { data, err : hujson.Standardize(data) if err ! nil { return err } return FormatJSON.Unmarshal(data, value) }标准化Standardizehujson.Standardize将 JSONC 文本中的注释剥离、移除尾随逗号并规范空白产出一份等价的标准 JSON标准解析标准化结果交给FormatJSON.Unmarshal即 format.go 中的严格 JSON 解码器完成真正的解析。formatJSONC同时实现了Marshal见 format.go先用 Go 标准库json.Encoder编码关闭 HTML 转义再用hujson.Format输出人类友好的 JSONC 排版。这意味着FormatJSONC在 chezmoi 内部被当作一种一等序列化格式对待与json、toml、yaml并列注册于FormatsByName与FormatsByExtension映射中见 format.go。严格的 JSON 解码细节FormatJSON.Unmarshal使用了json.Decoder的DisallowUnknownFields()并在解码到通用类型时启用UseNumber()以保留数字精度随后做一次只允许单一顶层值的 EOF 校验见 format.go。这些约束同样作用于fromJsonc的解析结果。数字类型转换规则fromJsonc与fromJson一样在数字处理上比 Go 标准库encoding/json更智能。根据 format.go 的replaceJSONNumbersWithNumericValues逻辑解析出的 JSON 数字按如下优先级转换能被精确表示为 64 位有符号整数int64的数字返回int64否则若在 64 位 IEEE 浮点数范围内返回float64否则超出两者表示范围以字符串形式返回以保留原始数值如 format.go 注释所述这类值合法但实际罕见参见 RFC 7159 Section 6。这一规则与 fromJson.md 中fromJson的行为完全一致保证模板中做数值运算如add、mul时能拿到真正的数字而非字符串。实战用法在 execute-template 中解析标准输入最直接的用法是借助--with-stdin将文件内容注入模板上下文.chezmoi.stdin再用fromJsonc解析。chezmoi 的集成测试 templatefuncs.txtar 给出了完整可复现的示例// 输入文件 example.jsonc { key: 1, // Comment }chezmoi execute-template --with-stdin {{ fromJsonc .chezmoi.stdin | toJson }} # 输出 {key:1}可以看到输入中的// Comment注释被正确剥离toJson输出为标准 JSON 格式。在模板文件中读取带注释的配置fromJsonc也常用于源文件模板内部读取机器上已有的 JSONC 风格配置文件作为模板数据。例如{{- $config : fromJsonc (include ~/.config/editor/settings.jsonc) -}} {{ $config.theme | default dark }}这里的include负责读取文件内容支持~展开fromJsonc将其解析为字典随后即可通过点路径访问嵌套字段配合default提供回退值。结合管道与其他函数使用由于fromJsonc返回值是any类型天然适合接入管道配合toJson、toYaml、index、hasKey、get等函数做后续处理。比如将 JSONC 配置整体转成 YAML 输出chezmoi execute-template --with-stdin {{ fromJsonc .chezmoi.stdin | toYaml }}错误处理与边界情况fromJsonc对非法输入直接报错panic 后转为 chezmoi 错误消息。format_test.go 用一组表格测试完整覆盖了FormatJSONC的边界行为可作为排查解析问题的参考输入结果{key:value} // comment解析成功值为{key:value}{key:value}解析成功空输入报错parsing value: unexpected EOF{key:value}1顶层多余值报错invalid character 1 after top-level value{unknown:value}未知字段报错json: unknown field unknown{意外 EOF报错parsing value: unexpected EOF\n仅空白报错parsing value: unexpected EOF这些用例揭示了几条实用结论顶层必须恰好是一个值JSONC 内容之后若还有多余 token如}1会失败避免静默丢弃数据不允许未知字段在需要严格校验结构的场景中结合具名结构体解析DisallowUnknownFields会拒绝未声明的键空白与空输入视为错误与fromYaml对空输入宽容不同见 format.gofromJsonc要求内容非空。在 chezmoi 代码库中的真实应用fromJsonc的底层格式FormatJSONC并非仅服务模板函数它还被 chezmoi 自身用于解析真实世界中的 JSONC 文件。最典型的例子在 upgradecmd_windows.gochezmoi 在 Windows 上升级时会读取微软 WinGet 的settings.json该文件允许注释属 JSONC 格式来判断可移植包安装位置settingsPaths : []string{ os.ExpandEnv(${LOCALAPPDATA}\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\settings.json), os.ExpandEnv(${LOCALAPPDATA}\Microsoft\WinGet\Settings\settings.json), } for _, settingsPath : range settingsPaths { if _, err : os.Stat(settingsPath); err nil { winGetSettingsContents, err : os.ReadFile(settingsPath) if err nil { if err : chezmoi.FormatJSONC.Unmarshal(winGetSettingsContents, winGetSettings); err ! nil { return false, err } } } }这印证了FormatJSONC即fromJsonc的底层对人类可读配置的解析能力是经过真实场景验证的——同样是带注释的 JSON 配置文件在模板中你可以用fromJsonc在 Go 代码中可以直接用chezmoi.FormatJSONC.Unmarshal。与其他解析函数的对比与选择chezmoi 提供了完整的反序列化函数家族注册表见 config.go函数解析格式典型场景fromJson严格 JSON标准的 JSON API 响应、纯 JSON 配置fromJsoncJSONC注释 尾随逗号允许注释的配置文件如 WinGet、VS Code 风格fromTomlTOMLRust/Cargo 风格的配置文件fromYamlYAMLKubernetes、Ansible 等 YAML 生态选型建议当数据来源可能带注释、或来源是人工维护的 JSONC 配置时用fromJsonc当数据来自程序生成的严格 JSON 时用fromJson即可。若数据可能包含注释但不确定直接选用fromJsonc是更稳妥的选择因为它兼容标准 JSON 的全部语法仅是放宽了注释与尾随逗号的限制。小结fromJsonc以极小的 API 面一个字符串参数、一个任意类型返回值提供了 JSONC 解析能力其背后是hujson 标准化 严格 JSON 解码的两步流水线以及 int64/float64/string 三级数字保真策略。无论是通过chezmoi execute-template --with-stdin快速解析带注释的配置还是在源文件模板中读取机器上的 JSONC 文件fromJsonc都让人类友好的 JSON与模板可用的结构化数据无缝衔接是处理配置类数据源时值得优先考虑的工具。【免费下载链接】chezmoiManage your dotfiles across multiple diverse machines, securely.项目地址: https://gitcode.com/gh_mirrors/ch/chezmoi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门