将哈希转换为对象

heh*_*uhu 17 ruby hash ruby-on-rails

我试图将哈希和嵌套哈希转换为对象.

到目前为止,第一个哈希对象由此代码成功转换:

class Hashit
  def initialize(hash)
    hash.each do |k,v|
      self.instance_variable_set("@#{k}", v)
      self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")})
      self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)})
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

但问题是,我还想转换嵌套的哈希对象.但无法成功.

h = Hashit.new({a: '123r', b: {c: 'sdvs'}})
 => #<Hashit:0x00000006516c78 @a="123r", @b={:c=>"sdvs"}> 
Run Code Online (Sandbox Code Playgroud)

@b={:c=>"sdvs"}在输出中看到这部分.我也想将它转换为对象.是的,如果是,那怎么样?

小智 48

您可以使用OpenStruct http://ruby-doc.org/stdlib-2.0.0/libdoc/ostruct/rdoc/OpenStruct.html

user = OpenStruct.new({name: "Jimmy Cool", age: "25"})
user.name #Jimmy Cool
user.age #25
Run Code Online (Sandbox Code Playgroud)

  • 这种方式不是递归的。你不能使用“object.abc”,只能使用“object.a”。 (3认同)
  • 这是最好的答案! (2认同)

Vla*_*nev 37

另一种方法是使用JSON和OpenStruct,它们是标准的ruby库:

irb:
> require 'JSON'
=> true

> r = JSON.parse({a: { b: { c: 1 }}}.to_json, object_class: OpenStruct)
=> #<OpenStruct a=#<OpenStruct b=#<OpenStruct c=1>>>

> r.a.b.c
=> 1
Run Code Online (Sandbox Code Playgroud)

  • 哦,我已经错过了_years_! (2认同)

Tho*_*tre 7

您需要添加递归性:

class Hashit
  def initialize(hash)
    hash.each do |k,v|
      self.instance_variable_set("@#{k}", v.is_a?(Hash) ? Hashit.new(v) : v)
      self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")})
      self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)})
    end
  end
end

h = Hashit.new({a: '123r', b: {c: 'sdvs'}})
# => #<Hashit:0x007fa6029f4f70 @a="123r", @b=#<Hashit:0x007fa6029f4d18 @c="sdvs">>
Run Code Online (Sandbox Code Playgroud)