summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2013-02-11 14:39:06 -0800
committerdanielsdeleo <dan@opscode.com>2013-02-11 14:39:06 -0800
commit4838812f4b29caec0cee44adac358fc1da249f8d (patch)
treec0050ff8ce2f37744a1ddd6b2640f76cd5aecbd1
parentab0570b03b6e2227d2dc8cb55ebb20396898fe8e (diff)
downloadchef-4838812f4b29caec0cee44adac358fc1da249f8d.tar.gz
Add json_class support w/o JSON for most types
-rw-r--r--lib/chef/json_compat.rb62
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