diff options
author | danielsdeleo <dan@opscode.com> | 2013-02-11 14:39:06 -0800 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2013-02-11 14:39:06 -0800 |
commit | 4838812f4b29caec0cee44adac358fc1da249f8d (patch) | |
tree | c0050ff8ce2f37744a1ddd6b2640f76cd5aecbd1 /lib/chef/json_compat.rb | |
parent | ab0570b03b6e2227d2dc8cb55ebb20396898fe8e (diff) | |
download | chef-4838812f4b29caec0cee44adac358fc1da249f8d.tar.gz |
Add json_class support w/o JSON for most types
Diffstat (limited to 'lib/chef/json_compat.rb')
-rw-r--r-- | lib/chef/json_compat.rb | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb index 9f59a41839..71654b5182 100644 --- a/lib/chef/json_compat.rb +++ b/lib/chef/json_compat.rb @@ -24,6 +24,8 @@ class Chef class JSONCompat JSON_MAX_NESTING = 1000 + JSON_CLASS = "json_class".freeze + class <<self # See CHEF-1292/PL-538. Increase the max nesting for JSON, which defaults # to 19, and isn't enough for some (for example, a Node within a Node) @@ -38,7 +40,37 @@ class Chef # Just call the JSON gem's parse method with a modified :max_nesting field def from_json(source, opts = {}) - ::JSON.parse(source, opts_add_max_nesting(opts)) + obj = ::Yajl::Parser.parse(source) + if opts[:create_additions].nil? || opts[:create_additions] + map_to_rb_obj(obj) + else + obj + end + end + + def map_to_rb_obj(json_obj) + res = case json_obj + when Hash + mapped_hash = map_hash_to_rb_obj(json_obj) + if json_obj.has_key?(JSON_CLASS) && (class_to_inflate = class_for_json_class(json_obj[JSON_CLASS])) + class_to_inflate.json_create(mapped_hash) + else + mapped_hash + end + when Array + json_obj.map {|e| map_to_rb_obj(e) } + else + json_obj + end + res + end + + def map_hash_to_rb_obj(json_hash) + mapped_hash = {} + json_hash.each do |key, value| + mapped_hash[key] = map_to_rb_obj(value) + end + mapped_hash end def to_json(obj, opts = nil) @@ -48,6 +80,34 @@ class Chef def to_json_pretty(obj, opts = nil) ::JSON.pretty_generate(obj, opts_add_max_nesting(opts)) end + + def class_for_json_class(json_class) + case json_class + when "Chef::ApiClient" + Chef::ApiClient + when "Chef::CookbookVersion" + Chef::CookbookVersion + when "Chef::DataBag" + Chef::DataBag + when "Chef::DataBagItem" + Chef::DataBagItem + when "Chef::Environment" + Chef::Environment + when "Chef::Node" + Chef::Node + when "Chef::Role" + Chef::Role + when "Chef::Sandbox" + false + when "Chef::Resource" + false + when "Chef::ResourceCollection" + Chef::ResourceCollection + else + raise ArgumentError, "Unsupported `json_class` type '#{json_class}'" + end + end + end end end |