在日常开发中,我们经常需要在配置文件(如 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 解析器将其结构化。
六、延伸阅读
- YAML 官方规范
- Go
text/template文档 - Helm 模板函数指南
💡 小贴士 :在 Helm 中,官方已内置
fromJson和toJSON函数,无需手动实现!
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!也欢迎在评论区交流你在 YAML/JSON 处理中遇到的坑 😊