在 YAML 中如何将 JSON 对象作为字符串整体赋值?——兼谈 Go Template 中的 fromJson 使用

在日常开发中,我们经常需要在配置文件(如 YAML)中嵌入一段 JSON 数据。有时,这段 JSON 并不是要被 YAML 解析器当作结构化对象处理,而是作为一个完整的字符串 传递给下游系统(比如 Go 模板、Helm Chart 或微服务配置)。那么,如何在 YAML 中正确地将一个 JSON 对象表示为字符串?本文将为你详细解答,并结合 Go Template 中的 fromJson 函数说明其典型应用场景。


一、问题背景

假设我们有如下 JSON 数据:

json 复制代码
{
  "name": "Alice",
  "age": 30,
  "hobbies": ["reading", "swimming"]
}

现在,我们需要将它作为一个字符串赋值给 YAML 文件中的某个字段,例如:

yaml 复制代码
data: ??? # 这里应该填什么?

注意:我们的目标是让 data 的值是一个字符串,而不是一个 YAML 映射(map)!


二、错误做法:直接写成 YAML 结构

很多初学者会这样写:

yaml 复制代码
# ❌ 错误!这会被解析为 map,不是字符串
data:
  name: Alice
  age: 30
  hobbies:
    - reading
    - swimming

这样写虽然语义上等价,但 data 是一个对象(map) ,而不是字符串。如果你后续要用 fromJson 去解析它,就会失败------因为它根本就不是 JSON 字符串!


三、正确做法:将 JSON 作为字符串嵌入 YAML

✅ 方法 1:使用单引号包裹(推荐)

yaml 复制代码
data: '{"name": "Alice", "age": 30, "hobbies": ["reading", "swimming"]}'
  • 单引号内的内容在 YAML 中不会转义,原样保留。
  • 简洁、安全、可读性好。
  • 是最常用的方式。

✅ 方法 2:使用双引号 + 转义(不推荐,但合法)

yaml 复制代码
data: "{\"name\": \"Alice\", \"age\": 30, \"hobbies\": [\"reading\", \"swimming\"]}"
  • 需要手动转义内部的双引号,容易出错。
  • 仅在特殊场景下使用。

✅ 方法 3:使用折叠块标量 >-(适合长 JSON)

yaml 复制代码
data: >-
  {"name": "Alice", "age": 30, "hobbies": ["reading", "swimming"]}
  • >- 表示"折叠换行并去除末尾换行",最终得到单行字符串。
  • 如果你为了可读性想分行写 JSON,需谨慎:YAML 会把换行转为空格,可能导致 JSON 格式错误。

🚫 不要使用 |(保留换行),因为会在字符串末尾添加 \n,破坏 JSON 合法性。


四、实际应用场景:Go Template 中的 fromJson

在 Helm、Kubernetes 或自定义 Go 应用中,我们常通过模板动态渲染配置。此时,fromJson 就派上用场了。

1. 定义 fromJson 函数

go 复制代码
func fromJSON(jsonStr string) interface{} {
    var result interface{}
    if err := json.Unmarshal([]byte(jsonStr), &result); err != nil {
        return map[string]interface{}{} // 安全兜底
    }
    return result
}

2. 注册到模板函数

go 复制代码
tmpl := template.Must(template.New("example").Funcs(template.FuncMap{
    "fromJson": fromJSON,
}).Parse(`...`))

3. 在模板中使用

假设 values.yaml 如下:

yaml 复制代码
userData: '{"name": "Alice", "age": 30, "hobbies": ["reading", "swimming"]}'

模板内容:

go 复制代码
{{- $user := fromJson .Values.userData }}
Name: {{ $user.name }}
Age: {{ $user.age }}
Hobbies: {{ join ", " $user.hobbies }}

输出结果:

复制代码
Name: Alice
Age: 30
Hobbies: reading, swimming

✅ 成功将 YAML 中的 JSON 字符串解析为结构化数据!


五、总结

场景 推荐写法
短 JSON 字符串 '{"key":"value"}'(单引号)
长 JSON(需换行) 谨慎使用 >-,确保无格式破坏
避免 直接写 YAML 结构(会被解析为 map)

记住:当你需要把 JSON 当作字符串传递时,必须用引号包裹,防止 YAML 解析器将其结构化。


六、延伸阅读


💡 小贴士 :在 Helm 中,官方已内置 fromJsontoJSON 函数,无需手动实现!

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!也欢迎在评论区交流你在 YAML/JSON 处理中遇到的坑 😊

相关推荐
molaifeng19 小时前
Go 语言如何实现高性能网络 I/O:Netpoller 模型揭秘
开发语言·网络·golang
韩师学子--小倪19 小时前
fastjson与gson的toString差异
java·json
Drawing stars19 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
nbsaas-boot19 小时前
SQL Server 存储过程开发规范(公司内部模板)
java·服务器·数据库
行百里er20 小时前
用 ThreadLocal + Deque 打造一个“线程专属的调用栈” —— Spring Insight 的上下文管理术
java·后端·架构
玄〤20 小时前
黑马点评中 VoucherOrderServiceImpl 实现类中的一人一单实现解析(单机部署)
java·数据库·redis·笔记·后端·mybatis·springboot
J_liaty20 小时前
Spring Boot拦截器与过滤器深度解析
java·spring boot·后端·interceptor·filter
亲爱的非洲野猪21 小时前
Java锁机制八股文
java·开发语言
rgeshfgreh21 小时前
C++字符串处理:STL string终极指南
java·jvm·算法
Zoey的笔记本21 小时前
「支持ISO27001的GTD协作平台」数据生命周期管理方案与加密通信协议
java·前端·数据库