为啥 YAML.safe_load 在 YAML 别名上失败?

Posted

技术标签:

【中文标题】为啥 YAML.safe_load 在 YAML 别名上失败?【英文标题】:Why is YAML.safe_load failing on a YAML alias?为什么 YAML.safe_load 在 YAML 别名上失败? 【发布时间】:2017-08-17 10:55:45 【问题描述】:

我的 Rails 应用程序中有一个区域设置文件,它可以在 Rails 上正常工作,但是当我尝试将它与 react_on_rails rake 任务 (rake react_on_rails:locale) 一起使用时,我收到了这个错误:

Psych::BadAlias: Unknown alias: item_attributes

发现rake任务基本是调用YAML.safe_load,于是准备了一个没有Rails的最简单的例子,错误依旧。这是示例 Ruby 脚本:

require 'yaml'

YAML.safe_load(File.open('test.yml'))

这是 test.yml 文件(实际语言环境文件的较短版本):

pl:
  language: Polski
  dictionary_name: simple
  activerecord:
    attributes:
      line_item: &item_attributes
        variant: Produkt
        quantity: Ilosc
        price: Cena Netto
        total_price: Wartosc Netto
        vat_rate: VAT
        total_vat_amount: Kwota VAT
        total_gross_price: Wartosc Brutto
      order_item:
        <<: *item_attributes

我仍然收到错误:

/usr/local/Cellar/ruby/2.3.1/lib/ruby/2.3.0/psych/visitors/to_ruby.rb:402:in `visit_Psych_Nodes_Alias': Unknown alias: item_attributes (Psych::BadAlias)

任何想法为什么这适用于 Rails 但在这里失败?是否有其他方法可以避免 YAML 文件中的重复并使其适用于 Rails 和 YAML.safe_load

【问题讨论】:

我猜YAML.safe_load 不支持&lt;&lt;。如果&lt;&lt;: foo: bar 有效,你可以试试。如果不是,这不是别名问题。 @flyx 是的,它确实有效,所以不是这样 确实很奇怪。这里没有 YAML 语法错误,可能涉及到两个不同的 YAML 解析器? 【参考方案1】:

我在 Psych 文档中找到了答案,地址为 https://ruby-doc.org/stdlib-2.1.0/libdoc/psych/rdoc/Psych.html

可以通过更改别名参数来明确允许别名。例如:

x = []
x << x
yaml = Psych.dump x
Psych.safe_load yaml               # => raises an exception
Psych.safe_load yaml, [], [], true # => loads the aliases

是否允许别名是一个布尔值作为第四个参数传递给safe_load

【讨论】:

2.6及以后版本,可以使用Psych.safe_load yaml, aliases: true # =&gt; loads the aliasesruby-doc.org/stdlib-2.6.3/libdoc/psych/rdoc/Psych.html

以上是关于为啥 YAML.safe_load 在 YAML 别名上失败?的主要内容,如果未能解决你的问题,请参考以下文章

pyyaml safe_load:如何忽略本地标签

了解 YAML 文件与数据配置

02-08 Python库-yaml

在 Python 中加载用 Jinja2 嵌套的 YAML

Python:使用“点表示法”访问 YAML 值

如何测试可能不存在的属性? [复制]