6

我有一个序列化的 JSON 字符串(实际上是厨师角色定义),它有一个 json_class 键,使 ruby​​ JSON 解析器尝试强制它成为 Chef::Role 对象。我怎样才能让解析器忽略这个键,只是简单地反序列化成一个普通的哈希?

4

4 回答 4

13

我刚刚遇到了同样的问题,并通过阅读 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应该用于解组转储对象。

于 2011-06-30T13:44:48.207 回答
6

“json_class”键用于指示 json 应该作为什么对象取消编组。它由 JSON.dump 添加。在更新的 JSON 版本中,JSON.parse将忽略“json_class”,取消编组为哈希。WhileJSON.load将取消编组到指示的对象(在您的情况下,是 Chef::Role)。

JSON.parse('{ "json_class": "Chef::Role" }').class => Hash
JSON.load('{ "json_class": "Chef::Role" }').class => Chef::Role
于 2013-03-29T17:26:01.410 回答
0

可以在解析之前对字符串执行 agsub操作,然后将该特定键更改为其他键。

如何在之前和之后显示 JSON 样本?

于 2011-02-03T01:46:15.283 回答
0

根据文档,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 是一个哈希,但只要 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 对,那么以后仍然可能会遇到麻烦,就像在这种情况下一样。

于 2014-03-12T04:47:14.610 回答