Я работаю с базой данных Rails, которая содержит сериализованные значения в одном столбце. Эти значения должны были быть обычными Hash
es, но из-за неправильной дезинфекции параметров они были сохранены как HashWithIndifferentAccess
или 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 ...
^
Поэтому по какой-то причине он ожидает конструктора. Но вполне очевидно, что сама ценность - это просто обычный словарь. Как я могу его прочитать?
Вы можете использовать add_constructor(loader, node)
парсера PyYAML, которая позволяет вам создавать пользовательские конструкторы для типов объектов, которые он не распознает.
В этом конструкторе функцию 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)
Это как- то документировано, но трудно найти много примеров.
params
? Они, вероятно, хотят сказатьparams.to_unsafe_h.to_yaml
вместоparams.to_yaml
.