Golang如何部分序列化YAML文件
Golang如何部分序列化YAML文件
假设我有一个大致如下的 yaml 文件:
apiVersion: flux.weave.works/v1beta1
kind: HelmRelease
metadata:
annotations:
flux.weave.works/ignore: 'false'
flux.weave.works/automated: 'false'
flux.weave.works/tag.redash: glob:*
name: redash
namespace: default
spec:
chart:
git: git@github.com:pkaramol/somerepo.git
path: charts/myapp
ref: mybranch
releaseName: redash
values:
namespace: default
redash-service:
istio:
enabled: true
namespace: default
image: redash/redash
tag: 8.0.0.
imagePullPolicy: Always
port: 5000
serviceType: ClusterIP
env:
config:
PYTHONUNBUFFERED: '0'
REDASH_LOG_LEVEL: 'INFO'
REDASH_REDIS_URL: 'redis://redis:6379/0'
redis:
namespace: default
istio:
enabled: true
replicas: 1
image: redis
tag: 5.0-alpine
port: 6379
imagePullPolicy: Always
serviceType: ClusterIP
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000M
memory: 1500Mi
someNode:
sealedsecrets:
releaseName_hash: 12345
anotherNode:
item1:
item2:
item3:
item4:
有没有办法只部分地解析它?也就是说,假设我只对 spec.values.sealedsecrets.anotherNode 感兴趣(我认为我应该能把它作为数组或切片获取回来)。
这可能实现吗?
更多关于Golang如何部分序列化YAML文件的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
谢谢,这正是我一直在寻找的。
出于某种原因,似乎找不到可以让我采纳你答案的复选框。
更多关于Golang如何部分序列化YAML文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
是的,使用 yaml 包,你无需解组完整的 YAML。以下代码可行:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"log"
)
type StructA struct {
A string `yaml:"a"`
}
type StructB struct {
StructA `yaml:"a"`
}
var data = `
b: some b
a:
a: the A
ignore: me
c:
nested: ignored
`
func main() {
var b StructB
err := yaml.Unmarshal([]byte(data), &b)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Println(b.A)
}
输出:
the A
在Go中可以使用yaml.v3库的部分解析功能来实现YAML文件的部分序列化。以下是示例代码:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
)
func main() {
// 读取YAML文件
data, err := ioutil.ReadFile("config.yaml")
if err != nil {
panic(err)
}
// 定义只包含所需字段的结构体
var partial struct {
Spec struct {
Values struct {
SealedSecrets struct {
AnotherNode map[string]interface{} `yaml:"anotherNode"`
} `yaml:"sealedsecrets"`
} `yaml:"values"`
} `yaml:"spec"`
}
// 部分解析YAML
err = yaml.Unmarshal(data, &partial)
if err != nil {
panic(err)
}
// 访问目标数据
anotherNode := partial.Spec.Values.SealedSecrets.AnotherNode
fmt.Printf("anotherNode: %v\n", anotherNode)
// 如果需要将anotherNode转换为切片
var items []interface{}
for key, value := range anotherNode {
items = append(items, map[string]interface{}{
"key": key,
"value": value,
})
}
fmt.Printf("作为切片: %v\n", items)
}
或者使用更灵活的方式,通过yaml.Node进行手动解析:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
)
func main() {
data, err := ioutil.ReadFile("config.yaml")
if err != nil {
panic(err)
}
var root yaml.Node
err = yaml.Unmarshal(data, &root)
if err != nil {
panic(err)
}
// 手动遍历节点查找目标路径
var targetNode *yaml.Node
findNode(&root, []string{"spec", "values", "sealedsecrets", "anotherNode"}, 0, &targetNode)
if targetNode != nil {
// 解析目标节点
var result map[string]interface{}
err = targetNode.Decode(&result)
if err != nil {
panic(err)
}
fmt.Printf("anotherNode: %v\n", result)
}
}
func findNode(node *yaml.Node, path []string, depth int, result **yaml.Node) {
if depth >= len(path) {
*result = node
return
}
if node.Kind == yaml.MappingNode {
for i := 0; i < len(node.Content); i += 2 {
keyNode := node.Content[i]
valueNode := node.Content[i+1]
if keyNode.Value == path[depth] {
findNode(valueNode, path, depth+1, result)
return
}
}
}
}
如果需要将anotherNode的内容作为数组处理,可以这样解析:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
func main() {
yamlStr := `...` // 你的YAML内容
var config map[string]interface{}
err := yaml.Unmarshal([]byte(yamlStr), &config)
if err != nil {
panic(err)
}
// 使用类型断言安全地访问嵌套字段
spec, _ := config["spec"].(map[string]interface{})
values, _ := spec["values"].(map[string]interface{})
sealedSecrets, _ := values["sealedsecrets"].(map[string]interface{})
anotherNode, _ := sealedSecrets["anotherNode"].(map[string]interface{})
// 转换为切片
var sliceResult []map[string]interface{}
for k, v := range anotherNode {
sliceResult = append(sliceResult, map[string]interface{}{
"key": k,
"value": v,
})
}
fmt.Printf("作为切片: %v\n", sliceResult)
}
这些方法都能实现YAML文件的部分解析,只提取spec.values.sealedsecrets.anotherNode部分的数据。第一种方法最简洁,直接通过定义部分结构体来解析;第二种方法最灵活,可以处理动态路径;第三种方法适合处理不确定结构的YAML数据。

