【发布时间】:2014-03-12 13:14:27
【问题描述】:
我有一个序列化的 JSON 字符串(实际上是厨师角色定义),它有一个 json_class 键,使 ruby JSON 解析器尝试将其强制为 Chef::Role 对象。我怎样才能让解析器忽略这个键而只是简单地反序列化成一个普通的哈希?
【问题讨论】:
标签: ruby json chef-infra
我有一个序列化的 JSON 字符串(实际上是厨师角色定义),它有一个 json_class 键,使 ruby JSON 解析器尝试将其强制为 Chef::Role 对象。我怎样才能让解析器忽略这个键而只是简单地反序列化成一个普通的哈希?
【问题讨论】:
标签: ruby json chef-infra
我刚刚遇到了同样的问题,并通过阅读 JSON gem 的源代码找到了答案 - 只是在尝试进行解析之前取消设置 JSON.create_id:
JSON.create_id = nil
JSON.parse('{ "json_class": "Chef::Role" }').class => Hash
编辑:请注意,由于 gem 的 1.7 版(我键入此更新时为 1.8.0 版),因此不再需要上述 hack。 JSON#parse 现在忽略 json_class,而应使用 JSON#load 来解组转储对象。
【讨论】:
“json_class”键用于指示 json 应该被解组为什么对象。它由 JSON.dump 添加。在更新的 JSON 版本中,JSON.parse 将忽略“json_class”,取消编组为哈希。而JSON.load 将取消编组到指定的对象(在您的情况下,是 Chef::Role)。
JSON.parse('{ "json_class": "Chef::Role" }').class => Hash
JSON.load('{ "json_class": "Chef::Role" }').class => Chef::Role
【讨论】:
您可以在解析之前对字符串执行gsub,然后将该特定键更改为其他键。
展示一个前后的 JSON 样本怎么样?
【讨论】:
根据文档,Mark Reed 的解决方案肯定可以工作。但是当我在 Vagrantfile 中尝试这个时:
JSON.create_id = nil
vagrant_json = JSON.parse(Pathname(__FILE__).dirname.join('nodes', "#{node_name}.json").read)
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
chef.roles_path = "roles"
chef.data_bags_path = "data_bags"
chef.node_name = node_name
chef.run_list = vagrant_json.delete('run_list')
chef.json = vagrant_json
end
vagrant_json.class 是一个 Hash,但只要 node.json 文件包含 "json_class": "Chef::Node" 条目,它仍会在内部保留 json_class 值。然后在最后一行使用哈希设置 chef.json 值时,再次使用 json 类对其进行解释(奇怪的是,结果是一个空的运行列表。)
这是有效的。相同的想法,但技巧少了一点:
vagrant_json = JSON.parse(Pathname(__FILE__).dirname.join('nodes', "#{node_name}.json").read)
vagrant_json['json_class'] = nil # <== This worked
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
chef.roles_path = "roles"
chef.data_bags_path = "data_bags"
chef.node_name = node_name
chef.run_list = vagrant_json.delete('run_list')
chef.json = vagrant_json
end
此代码用于从 Chef 节点文件设置 json 属性和运行列表,无论是否带有 "json_class": "Chef::Node" 条目。
总之,关于从 JSON.parse 获取哈希,前面的答案似乎完全正确,但如果您不从该哈希中删除 json_class 对,那么以后仍然可能会出现问题,就像在这种情况下一样。
【讨论】: