2 回答
TA贡献1799条经验 获得超9个赞
另一方面,如果我使用(在这种情况下)[]yaml.Node 结构,它确实在内部将所有节点表示为 yaml.Node 或 []yaml.Node。
这是不准确的。go-yaml 允许您保留结构的任何子树以yaml.Node供以后处理。在这个节点内,一切都表示为yaml.Node,而作为集合(序列或映射)的节点恰好将其子节点存储为[]yaml.Node。但没有节点直接表示为[]yaml.Node。
当您反序列化 into[]yaml.Node时,您将顶级节点反序列化为本机结构(切片),同时不构造子节点(将 YAML 节点加载到本机结构的过程在规范中称为构造)。
go-yaml 真的不支持
type Document yaml.Node
但如果你只是这样做
var d yaml.Node
评论也将被保留(toSlice显然不再起作用):
- # Employee records
martin:
name: Martin D'vloper
job: Developer
skills:
- python
- perl
- pascal
- tabitha:
name: Tabitha Bitumen
job: Developer
skills:
- lisp
- fortran
- erlang
现在我们可以看到,评论的位置不同了。这是因为 go-yaml 只是在yaml.Node表示列表项的 中存储“在此列表项之前有一个评论”。有关评论的确切位置的信息丢失了。你应该感谢你有关于评论的任何信息,因为大多数 YAML 实现更早地废弃它们,因为规范说评论不能传达内容信息。
您可能想阅读我想加载 YAML 文件,可能编辑数据,然后再次转储。如何保留格式?其中详细介绍了在加载 YAML 文件期间信息丢失的原因、时间和方式。TL; DR:不可能(基本上不自己解析)加载 YAML 文件并将其转储回同时保留所有格式,如果这是您的目标,那么 YAML 对您来说是错误的工具。
TA贡献1779条经验 获得超6个赞
go-yaml 解析 YAML 文档时,总是先创建 YAML 节点树。然后它是否将该节点树转换为普通的 Golang 对象,取决于out传递给Unmarshall. 这是来自 go-yaml 来源的代码片段:
func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
// ...
if out.Type() == nodeType {
out.Set(reflect.ValueOf(n).Elem())
return true
}
// ...
}
本质上,如果提供的参数是指向yaml.Node. 当您的参数类型是interface{}或以外的任何其他内容yaml.Node时,它将进行转换。
为了保留注释并在顶层允许映射、数组甚至单个值,只需将 a*yaml.Node作为第二个参数传递给yaml.Unmarshal:
var n yaml.Node
err := yaml.Unmarshal(bytes, &n)
如果数组位于顶层,根节点将包含数组元素的 YAML 节点作为其子节点。
- 2 回答
- 0 关注
- 562 浏览
添加回答
举报
