news 2026/9/20 21:02:52

chezmoi 模板函数 `toPrettyJson` 全解:从缩进控制到源码级实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
chezmoi 模板函数 `toPrettyJson` 全解:从缩进控制到源码级实现
  • 开发工具
  • CLI
  • 配置管理

【免费下载链接】chezmoi

Manage your dotfiles across multiple diverse machines, securely.

项目地址:https://gitcode.com/gh_mirrors/ch/chezmoi
点击查看免费下载

toPrettyJson是 chezmoi 模板体系中用于生成“美化排版 JSON”的核心函数:它把任意模板值序列化为带缩进的 JSON 字符串,并允许调用者自定义缩进字符串。本文以 官方参考文档 为骨架,结合 templatefuncs.go 的实现与 templatefuncs.txtar 的测试用例,讲解参数语义、源码原理、与toJson的差异以及三种实战用法,读完即可在 dotfiles 模板中熟练输出可读 JSON。

函数签名与参数语义

toPrettyJson的调用形式为:

toPrettyJson [indent] value
  • value:任意模板值(map、list、字符串、数字等),将被序列化为 JSON。
  • indent(可选):嵌套元素相对父级的缩进字符串。默认值为两个空格" ")。

原文档给出的最小示例:

{{ dict "a" (dict "b" "c") | toPrettyJson "\t" }}

该表达式先用dict构造嵌套字典{"a": {"b": "c"}},再通过管道交给toPrettyJson "\t",输出结果约为:

{ "a": { "b": "c" } }

由于indent是任意字符串,你可以传入"\t"(制表符)、" "(四个空格)甚至" "以外的任意组合,灵活适配不同团队或工具的缩进规范。

源码实现:默认缩进与参数校验

在 internal/cmd/templatefuncs.go 中,Config.toPrettyJsonTemplateFunc完整展现了该函数的底层逻辑:

func (c *Config) toPrettyJsonTemplateFunc(args ...any) string { //nolint:revive,staticcheck var ( indent = " " value any ) switch len(args) { case 1: value = args[0] case 2: var ok bool indent, ok = args[0].(string) if !ok { panic(fmt.Errorf("arg 1: expected a string, got a %T", args[0])) } value = args[1] default: panic(fmt.Errorf("expected 1 or 2 arguments, got %d", len(args))) } var builder strings.Builder encoder := json.NewEncoder(&builder) encoder.SetEscapeHTML(false) encoder.SetIndent("", indent) must(encoder.Encode(value)) return builder.String() }

从中可以提炼出几条可验证的实现事实:

  • 参数个数:严格接受 1 个(仅value)或 2 个(indent, value)参数,其余数量会触发 panic,提示expected 1 or 2 arguments
  • 参数类型:第一个参数必须是string,否则 panic 并报出实际类型(arg 1: expected a string, got a %T)。
  • 默认缩进indent变量初始化为" "(两个空格),与文档声明完全一致。
  • 输出实现:基于标准库encoding/jsonEncoder,通过SetIndent("", indent)实现美化排版,SetEscapeHTML(false)关闭 HTML 字符转义,最终以strings.Builder收集输出。

该函数在 internal/cmd/config.go 中被加入白名单,并在 internal/cmd/config.go 注册为模板函数"toPrettyJson": c.toPrettyJsonTemplateFunc,因此它在所有 chezmoi 模板(包括普通.tmpl文件与execute-template命令)中开箱即用。

toJson的关键区别:HTML 字符不转义

toPrettyJsontoJson最值得注意的行为差异是HTML 转义。源码中显式调用了encoder.SetEscapeHTML(false),这意味着&<>等字符会原样输出,而不是被编码为\u0026\u003c\u003e

这一点由 internal/cmd/testdata/scripts/templatefuncs.txtar 中的回归测试直接锁定:

# test that the toPrettyJson template function does not escape HTML characters, ... exec chezmoi execute-template '{{ dict "a" (dict "b" "&") | toPrettyJson " " }}' cmp stdout golden/toPrettyJson

其期望输出(同文件 L336-L341):

{ "a": { "b": "&" } }

作为对照,chezmoi 在设置formatIndent时会对toJson进行覆盖实现,见 internal/chezmoi/template.go,该实现并未关闭 HTML 转义。因此当模板数据包含 URL 中的&、HTML 标签字符时,toPrettyJson输出的内容更“原始”、更接近直接手写的 JSON,尤其适合生成需要被其他程序(如 jq、curl、配置文件解析器)再次读取的中间数据。

实战一:在execute-template中调试与生成 JSON

execute-template是验证和生成模板输出的标准入口。例如:

chezmoi execute-template '{{ dict "name" "chezmoi" "version" "2" | toPrettyJson }}'

输出(默认两空格缩进):

{ "name": "chezmoi", "version": "2" }

如需指定缩进,将indent作为第一个参数传入:

chezmoi execute-template '{{ dict "a" (dict "b" 1) | toPrettyJson "\t" }}'

实战二:modify-template 中“读改写” JSON 文件

toPrettyJson最常见的生产用途是与fromJsonsetValueAtPath配合,在modify-template脚本里对既有 JSON 文件做定点修改。官方在 manage-different-types-of-file.md 中给出的模板为:

{{- /* chezmoi:modify-template */ -}} {{ fromJson .chezmoi.stdin | setValueAtPath "key.nestedKey" "value" | toPrettyJson }}

执行流程是:fromJson解析 stdin 中的原始 JSON →setValueAtPath设置嵌套路径的值 →toPrettyJson把修改后的结构重新输出为排版整齐的 JSON。由于toPrettyJson不会转义 HTML 字符,原文件中的&等字符在重写后得以原样保留,避免“读一次就变一次”的意外内容漂移。需要特别注意的是,modify-template 文件不能带.tmpl扩展名,否则不会被识别为修改模板。

配套函数矩阵

toPrettyJson并非孤立存在,它属于 chezmoi 的“编码/解码”函数家族,全部注册在 internal/cmd/config.go,并在 mkdocs.yml 中收录:

方向函数说明
解码fromJson/fromJsoncJSON / JSONC 字符串 → 模板值
解码fromTomlTOML 字符串 → 模板值
解码fromYamlYAML 字符串 → 模板值
编码toJson值 → 紧凑 JSON
编码toPrettyJson值 → 美化缩进 JSON(不转义 HTML)
编码toToml值 → TOML
编码toYaml值 → YAML
编码toInimap → INI 格式

由此可以组合出多种转换管线,例如从 YAML 读取配置、改写后再以 JSON 输出:fromYaml ... | toPrettyJson。无论哪种组合,toPrettyJson都承担着“最终交付可读 JSON”的收尾角色。

使用注意事项

  • 仅接受 1~2 个参数:多传或少传都会触发 panic,模板渲染直接失败,参数顺序必须是indent在前、value在后。
  • indent必须是字符串:传入非字符串类型(如数字)会以 panic 终止并提示期望类型。
  • 输出以换行结尾:底层json.Encoder.Encode会在 JSON 末尾追加一个换行符,若需嵌入其他模板上下文可配合trim使用。
  • 文档参考:完整定义见 toPrettyJson.md;如希望了解fromJson等反向解析函数的细节,可继续阅读同目录下的 fromJson.md、fromYaml.md 与 fromToml.md。

掌握toPrettyJson之后,你便能在 dotfiles 模板中随时生成结构清晰、可直接被下游工具消费的 JSON 输出——无论是调试数据、生成配置文件,还是对 JSON 类 dotfile 做无损的定点修改。

  • 开发工具
  • CLI
  • 配置管理

【免费下载链接】chezmoi

Manage your dotfiles across multiple diverse machines, securely.

项目地址:https://gitcode.com/gh_mirrors/ch/chezmoi
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 21:01:21

RapidOCR API Docker 部署:从镜像构建到上线检查的完整路径

RapidOCR API Docker 部署&#xff1a;从镜像构建到上线检查的完整路径 【免费下载链接】RapidOCR &#x1f4c4; Awesome OCR multiple programing languages toolkits based on ONNX Runtime, OpenVINO, MNN, PaddlePaddle, TensorRT and PyTorch. 项目地址: https://gitco…

作者头像 李华
网站建设 2026/9/20 21:01:05

AIOps 角色 IDENTITY 不生效?TaoToken 通道下给 OpenClaw 查模型配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 20:54:59

C语言Socket编程实战:手写TCP双端即时通讯完整教程

简介&#xff1a;这是一份以C语言实现双端即时通讯的教学演示项目&#xff0c;面向具备基础C语法、希望进阶网络编程的学习者&#xff0c;也适合高校网络编程课程作为实验参考。项目完整呈现了客户端与服务器从创建套接字、绑定地址、监听连接到收发消息、多线程处理请求的整个…

作者头像 李华