简体   繁体   English

将嵌套的 HashWithIndifferentAccess 转换为嵌套的 Hash

[英]Convert nested HashWithIndifferentAccess to nested Hash

Is there a nice way to transform an instance of a HashWithIndifferentAccess (with nested instances of class HashWithIndifferentAccess ) to an instance of a Hash (with nested instances of class Hash )?有没有一种很好的方法可以将 HashWithIndifferentAccess 的实例(具有HashWithIndifferentAccess HashWithIndifferentAccess的嵌套实例)转换为 Hash 的实例(具有 class Hash的嵌套实例)?

It seems easy to convert a nested Hash to a nested HashWithIndifferentAccess .将嵌套的HashWithIndifferentAccess转换为嵌套的Hash似乎很容易。 Just use the with_indifferent_access method that ActiveSupport provides.只需使用 ActiveSupport 提供的with_indifferent_access方法即可。 This converts all hashes, no matter how deeply nested.这会转换所有哈希,无论嵌套有多深。

hash = { late: { package: 2, trial: 100, penalty: { amount: 1 } },
         no_show: { package: 1, trial: 100, penalty: { amount: 2 } } }
hash_wid = hash.with_indifferent_access
hash_wid.class
# ActiveSupport::HashWithIndifferentAccess #great
hash_wid [:no_show][:penalty].class
# ActiveSupport::HashWithIndifferentAccess #great

The reverse seems not so easy:反过来似乎并不那么容易:

hash = hash_wid.to_h
hash.class
# Hash # OK
hash[:no_show][:penalty].class
# ActiveSupport::HashWithIndifferentAccess # want this to be Hash

Hash#to_h method only converts the top level hash, not the nested hashes. Hash#to_h方法只转换顶级 hash,而不是嵌套的哈希值。

I tried the (Rails/ActiveSupport) deep_transform_values!我尝试了 (Rails/ActiveSupport) deep_transform_values! method that extends the Hash class:扩展Hash class 的方法:

hash_wid.deep_transform_values! do |value|
  value.class == HashWithIndifferentAccess ? value.to_h : value
end
hash_wid.class
# ActiveSupport::HashWithIndifferentAccess # want this to be Hash
hash_wid[:no_show][:penalty].class
# ActiveSupport::HashWithIndifferentAccess # want this to be Hash

But looking to the source code of the deep_transform_values!但是要查看deep_transform_values! method (and transform_values! method that it depends upon), these can transform hashes of class Hash , but not hashes of class HashWithIndifferentAccess .方法(及其依赖的transform_values!方法),这些可以转换 class Hash的哈希值,但不能转换 class HashWithIndifferentAccess的哈希值。

So is there a nice way to transform a nested HashWithIndifferentAccess to a nested Hash ?那么有没有一种很好的方法可以将嵌套的HashWithIndifferentAccess转换为嵌套的Hash

Thanks谢谢

Daniel丹尼尔

Your example indicates that you are using keys and values whose types are compatible with JSON. If your hash can be converted to JSON then a simple way to do it is:您的示例表明您使用的键和值的类型与 JSON 兼容。如果您的 hash 可以转换为 JSON,那么一种简单的方法是:

hash = JSON.load(JSON.dump({ foo: { bar: 'baz' }.with_indifferent_access }.with_indifferent_access))
=> {"foo"=>{"bar"=>"baz"}}

hash.class
=> Hash

hash['foo'].class
=> Hash

deep_transform_values won't work in your case because of how that method is written :由于该方法的编写方式, deep_transform_values在您的情况下不起作用:

    def _deep_transform_values_in_object(object, &block)
      case object
      when Hash
        object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
      when Array
        object.map { |e| _deep_transform_values_in_object(e, &block) }
      else
        yield(object)
      end
    end

If your object is a Hash (or Array) then the method calls itself recursively until it finds a non-Hash and non-Array value onto which it can apply the transformation.如果您的 object 是一个 Hash(或数组),那么该方法会递归调用自身,直到它找到一个可以应用转换的非哈希和非数组值。 It should be pretty trivial to write your own implementation using that example though:不过,使用该示例编写自己的实现应该是非常简单的:

    def _deep_transform_values_in_object(object, &block)
      case object
      when Hash
        # something less ugly than but similar to this
        object = object.to_h if object.is_a?(ActiveSupport::HashWithIndifferentAccess)
        object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
      when Array
        object.map { |e| _deep_transform_values_in_object(e, &block) }
      else
        yield(object)
      end
    end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM