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

如何使用Python读取自定义序列化YAML对象(由Rails编写)?,python,ruby-on-rails,yaml,pyyaml,Python,Ruby On Rails,Yaml,Pyyaml,我正在使用一个Rails数据库,它在一列中包含序列化的值。这些值应该是常规的Hashes,但由于不正确地清理参数,它们被存储为hashwithindiffertaccess或parameters。例如,一个列条目如下所示: --- !ruby/object:ActionController::Parameters parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess windowHeight: 946 docume

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

--- !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 ...
        ^
***yaml.constructor.constructor错误:无法确定标记“”的构造函数!ruby/object:ActionController::Parameters'
在“”第1行第5列中:
--- !ruby/object:ActionController::P。。。
^

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

您可以使用PyYAML解析器的
add\u构造函数(loader,node)
函数,它允许您为无法识别的对象类型实现自定义构造函数

在该构造函数中,可以调用函数
loader.construct\u 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)

这是一个很好的例子,但是很难找到很多例子。

有没有可能将Rails代码修复为正确的Yamlized
params
?他们可能想说
params.to_unsafe\h.to_yaml
,而不是
params.to_yaml
@muistooshort是的,这正是我们现在为新条目所做的,慢慢地将旧条目迁移到正确的格式,但这需要一段时间。我以前遇到过这个问题(),在此过程中切换到JSON或其他东西可能是有意义的,但这可能超出了范围。