【问题标题】:Is it possible to preserve anchors, comments, and references when unmarshaling data structures back into YAML in Go?在 Go 中将数据结构解组回 YAML 时,是否可以保留锚点、注释和引用?
【发布时间】:2020-06-23 20:02:00
【问题描述】:

在 Go 中将数据结构解组回 YAML 时是否可以保留锚点等?

以下这些相关问题与使用 Python 的相同概念有关,使用 ruyamel.yaml 包似乎可行,并且根据文档 https://yaml.readthedocs.io/en/latest/example.html 似乎可以保留 cmets、锚点和引用。这称为“往返”。

使用https://github.com/go-yaml/yaml 的README.md 中的示例代码,我可以将yaml 文件读入数据结构。然后,我使用锚点和引用为精简文档导出了另一个示例。但是当转储回 YAML 时,锚定等就会丢失。可以在 Golang 中做同样的事情吗?

【问题讨论】:

    标签: go yaml


    【解决方案1】:

    go-yaml 有一个相当小的接口,因为它是 Go 包的典型接口。由于您可以访问的最低结构(通过Marshaler / Unmarshaler 接口)是yaml.Node,因此在不更改 go-yaml 本身的情况下,不可能用它实现往返(就像 ruamel 是PyYAML)。

    为了正确的往返,您需要:

    • 保留 cmets 和空白。这需要在词法分析器级别发生,很少有 YAML 实现在外部覆盖(libyaml 是我知道的唯一一个这样做的,但是你不能将词法分析器令牌反馈回它,所以它基本上没有用处)李>
    • 保留标量表示。这是最难做到的,因为引用的标量允许您转义任何 unicode 字符,并且如果您只有结果字符串,您将无法知道原始表示。我认为即使是 ruamel 也无法重现标量表示。标量表示还包括折叠标量中的换行符、chomping 和缩进指示符,这些都没有在 go-yaml 中公开。
    • 保留锚点和别名。 go-yaml 实际上允许您使用 Node.Anchor 访问它,但是您需要确定哪个是第一个具有锚点的节点,而其他的节点是最初的别名。这很困难,因为……
    • 保留密钥顺序。 YAML 定义映射中键的顺序不能传达内容信息。通常,映射加载在一个丢失此信息的哈希图中(如 Go 的 map 的情况)。但是,Node 确实提供了子项的原始顺序,所以这在 go-yaml 中是可行的。
    • 保留文档页眉和页脚。 YAML 允许在文档之前使用指令(%YAML%TAG),还允许文档以多个 ... 行结尾(以及中间的 cmets)。此信息不适用于 go-yaml。

    由于如果严格解释往返会违反 YAML 规范(因为它不允许表示细节对处理产生任何影响),它通常不是 YAML 实现的一部分,并且 afaik ruamel 是唯一尝试这样做的实现它。

    所以答案是:当然可以在 Go 中实现,但需要自己实现,可能通过 fork go-yaml 实现。由于解析 YAML 本身就非常复杂(see here,没有一个实现完全正确),一个涵盖所有边缘情况的正确 YAML 往返实现将非常复杂,我强烈建议不要这样做。

    【讨论】:

    • 感谢@flyx 的详细解答。
    猜你喜欢
    • 2016-04-09
    • 1970-01-01
    • 2018-06-06
    • 2018-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 2018-05-03
    相关资源
    最近更新 更多