如何使用Python读取自定义的序列化YAML对象(由Rails编写)?

时间:2018-07-16 18:05:40

标签: python ruby-on-rails yaml pyyaml

我正在使用在一个列中包含序列化值的Rails数据库。这些值应该是常规的Hash,但是由于不正确地清除了参数,它们被存储为HashWithIndifferentAccessParameters。例如,一个列条目如下所示:

--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  windowHeight: 946
  documentHeight: 3679
  scrollTop: 500
permitted: false

我想用Python的yaml实现来阅读它,但是当我尝试这样做时,我得到了:

*** yaml.constructor.ConstructorError: could not determine a constructor for the tag '!ruby/object:ActionController::Parameters'
  in "<unicode string>", line 1, column 5:
    --- !ruby/object:ActionController::P ...
        ^

因此,由于某种原因,它需要一个构造函数。但是很显然,该值本身只是一个常规字典。我怎么还能读呢?

1 个答案:

答案 0 :(得分:1)

您可以使用PyYAML解析器的add_constructor(loader, node)函数,该函数可让您为无法识别的对象类型实现自定义构造函数。

在该构造函数中,可以调用函数loader.construct_pairs(node)以从原始节点内容中获取键值元组。使用字典理解,我们可以创建原始字典。

由于条目是嵌套的,因此我们必须将构造函数应用于这两种对象类型。

完整的示例如下:

import yaml

def convert_entry(loader, node):
    return { e[0]: e[1] for e in loader.construct_pairs(node) }

yaml.add_constructor('!ruby/hash:ActiveSupport::HashWithIndifferentAccess', convert_entry)
yaml.add_constructor('!ruby/object:ActionController::Parameters', convert_entry)

yaml.load(input_string)

这是somehow documented,但很难找到很多示例。