Ruby 重写OpenStruct的getter以将其作为哈希打印

Ruby 重写OpenStruct的getter以将其作为哈希打印,ruby,openstruct,Ruby,Openstruct,目标:OpenStruct对象的值应作为哈希而不是对象打印 可能的解决方案:重写OpenStruct类的getter MyOpenStruct覆盖了OpenStruct的new、到和[] class MyOpenStruct < OpenStruct def initialize(object=nil) @table = {} @hash_table = {} if object object.each do

目标:OpenStruct对象的值应作为哈希而不是对象打印

可能的解决方案:重写OpenStruct类的getter

MyOpenStruct
覆盖了
OpenStruct的
new
[]

class MyOpenStruct < OpenStruct
    def initialize(object=nil)
        @table = {}
        @hash_table = {}

        if object
            object.each do |k,v|
                if v.is_a?(Array)
                    other = Array.new()
                    v.each { |e| other.push(self.class.new(entry)) }
                    v = other
                end
                @table[k.to_sym] = (v.is_a?(Hash) ? self.class.new(v) : v)
                @hash_table[k.to_sym] = v
                new_ostruct_member(k)
            end
        end
    end

    def [](val)
        @hash_table[val.to_sym]
    end
end
只有当我使用
[]
访问密钥时,才会返回哈希


如何更正此问题???

如果您将其作为散列返回,我认为创建嵌套OpenStruct没有意义。这就是OpenStruct的工作方式:

require 'ostruct'
struct = OpenStruct.new(name: 'first', place: { animal: 'thing' })
struct.place
# => {:animal=>"thing"}
struct.place[:animal]
# => "thing"
struct.place.animal
# => NoMethodError: undefined method `animal' for {:animal=>"thing"}:Hash
因此,如果您想使用点表示法获取
struct.place.animal
,您需要像以前一样创建嵌套的OpenStruct对象。 但是,正如我所说,您不需要重写
[]
方法。在不重写
[]
的情况下使用类,我得到以下结果:

struct = MyOpenStruct.new(name: 'first', place: { animal: 'thing' })
# => #<MyOpenStruct name="first", place=#<MyOpenStruct animal="thing">> 
struct.place
# => #<MyOpenStruct animal="thing"> 
struct.place.animal
# => "thing" 

我认为,如果您将其作为散列返回,那么创建嵌套的OpenStruct是没有意义的。这就是OpenStruct的工作方式:

require 'ostruct'
struct = OpenStruct.new(name: 'first', place: { animal: 'thing' })
struct.place
# => {:animal=>"thing"}
struct.place[:animal]
# => "thing"
struct.place.animal
# => NoMethodError: undefined method `animal' for {:animal=>"thing"}:Hash
因此,如果您想使用点表示法获取
struct.place.animal
,您需要像以前一样创建嵌套的OpenStruct对象。 但是,正如我所说,您不需要重写
[]
方法。在不重写
[]
的情况下使用类,我得到以下结果:

struct = MyOpenStruct.new(name: 'first', place: { animal: 'thing' })
# => #<MyOpenStruct name="first", place=#<MyOpenStruct animal="thing">> 
struct.place
# => #<MyOpenStruct animal="thing"> 
struct.place.animal
# => "thing" 

我认为,如果您将其作为散列返回,那么创建嵌套的OpenStruct是没有意义的。这就是OpenStruct的工作方式:

require 'ostruct'
struct = OpenStruct.new(name: 'first', place: { animal: 'thing' })
struct.place
# => {:animal=>"thing"}
struct.place[:animal]
# => "thing"
struct.place.animal
# => NoMethodError: undefined method `animal' for {:animal=>"thing"}:Hash
因此,如果您想使用点表示法获取
struct.place.animal
,您需要像以前一样创建嵌套的OpenStruct对象。 但是,正如我所说,您不需要重写
[]
方法。在不重写
[]
的情况下使用类,我得到以下结果:

struct = MyOpenStruct.new(name: 'first', place: { animal: 'thing' })
# => #<MyOpenStruct name="first", place=#<MyOpenStruct animal="thing">> 
struct.place
# => #<MyOpenStruct animal="thing"> 
struct.place.animal
# => "thing" 

我认为,如果您将其作为散列返回,那么创建嵌套的OpenStruct是没有意义的。这就是OpenStruct的工作方式:

require 'ostruct'
struct = OpenStruct.new(name: 'first', place: { animal: 'thing' })
struct.place
# => {:animal=>"thing"}
struct.place[:animal]
# => "thing"
struct.place.animal
# => NoMethodError: undefined method `animal' for {:animal=>"thing"}:Hash
因此,如果您想使用点表示法获取
struct.place.animal
,您需要像以前一样创建嵌套的OpenStruct对象。 但是,正如我所说,您不需要重写
[]
方法。在不重写
[]
的情况下使用类,我得到以下结果:

struct = MyOpenStruct.new(name: 'first', place: { animal: 'thing' })
# => #<MyOpenStruct name="first", place=#<MyOpenStruct animal="thing">> 
struct.place
# => #<MyOpenStruct animal="thing"> 
struct.place.animal
# => "thing" 

@多吉塔的回答在各方面都是正确的。我只是想回答你的问题“如果这不可能,那么我可以打印整个对象的散列吗
temp
?”是的,你可以。您只需将
重写为_h
,以递归方式遍历键和值,并将MyOpenStruct实例转换为哈希:

def to_h
  @table.each_with_object({}) do |(key, val), table|
    table[key] = to_h_convert(val)
  end
end

private
def to_h_convert(val)
  case val
  when self.class
    val.to_h
  when Hash
    val.each_with_object({}) do |(key, val), hsh|
      hsh[key] = to_h_convert(val)
    end
  when Array
    val.map {|item| to_h_convert(item) }
  else
    val
  end
end

@多吉塔的回答在各方面都是正确的。我只是想回答你的问题“如果这不可能,那么我可以打印整个对象的散列吗
temp
?”是的,你可以。您只需将
重写为_h
,以递归方式遍历键和值,并将MyOpenStruct实例转换为哈希:

def to_h
  @table.each_with_object({}) do |(key, val), table|
    table[key] = to_h_convert(val)
  end
end

private
def to_h_convert(val)
  case val
  when self.class
    val.to_h
  when Hash
    val.each_with_object({}) do |(key, val), hsh|
      hsh[key] = to_h_convert(val)
    end
  when Array
    val.map {|item| to_h_convert(item) }
  else
    val
  end
end

@多吉塔的回答在各方面都是正确的。我只是想回答你的问题“如果这不可能,那么我可以打印整个对象的散列吗
temp
?”是的,你可以。您只需将
重写为_h
,以递归方式遍历键和值,并将MyOpenStruct实例转换为哈希:

def to_h
  @table.each_with_object({}) do |(key, val), table|
    table[key] = to_h_convert(val)
  end
end

private
def to_h_convert(val)
  case val
  when self.class
    val.to_h
  when Hash
    val.each_with_object({}) do |(key, val), hsh|
      hsh[key] = to_h_convert(val)
    end
  when Array
    val.map {|item| to_h_convert(item) }
  else
    val
  end
end

@多吉塔的回答在各方面都是正确的。我只是想回答你的问题“如果这不可能,那么我可以打印整个对象的散列吗
temp
?”是的,你可以。您只需将
重写为_h
,以递归方式遍历键和值,并将MyOpenStruct实例转换为哈希:

def to_h
  @table.each_with_object({}) do |(key, val), table|
    table[key] = to_h_convert(val)
  end
end

private
def to_h_convert(val)
  case val
  when self.class
    val.to_h
  when Hash
    val.each_with_object({}) do |(key, val), hsh|
      hsh[key] = to_h_convert(val)
    end
  when Array
    val.map {|item| to_h_convert(item) }
  else
    val
  end
end


你的问题不清楚。你的目标是什么?您期望的输出是什么,而您得到的输出是什么?我希望
temp.place
返回散列,而不是
MyOpenConstruct
对象。凌驾于此无济于事。输入哈希可以比给定的哈希更深。每个访问都应该返回一个散列。如果以散列形式返回,为什么要创建嵌套的OpenStruct?@Doguita如何获得对值的点访问?我的意思是
temp.name
temp[:name]
将不一样。到目前为止,两者都在工作。只是我需要两个人都给我一份
temp.name
返回一个对象,但
temp[:name]
返回一个哈希值如果希望
place
返回不同的值,则需要在子类中重写它。对于
name
,同样如此。您的问题不清楚。你的目标是什么?您期望的输出是什么,而您得到的输出是什么?我希望
temp.place
返回散列,而不是
MyOpenConstruct
对象。凌驾于此无济于事。输入哈希可以比给定的哈希更深。每个访问都应该返回一个散列。如果以散列形式返回,为什么要创建嵌套的OpenStruct?@Doguita如何获得对值的点访问?我的意思是
temp.name
temp[:name]
将不一样。到目前为止,两者都在工作。只是我需要两个人都给我一份
temp.name
返回一个对象,但
temp[:name]
返回一个哈希值如果希望
place
返回不同的值,则需要在子类中重写它。对于
name
,同样如此。您的问题不清楚。你的目标是什么?您期望的输出是什么,而您得到的输出是什么?我希望
temp.place
返回散列,而不是
MyOpenConstruct
对象。凌驾于此无济于事。输入哈希可以比给定的哈希更深。每个访问都应该返回一个散列。如果以散列形式返回,为什么要创建嵌套的OpenStruct?@Doguita如何获得对值的点访问?我的意思是
temp.name
temp[:name]
将不一样。到目前为止,两者都在工作。只是我需要两个人都给我一份
temp.name
返回一个对象,但
temp[:name]
返回一个哈希值如果希望
place
返回不同的值,则需要在子类中重写它。对于
name
,同样如此。您的问题不清楚。你的目标是什么?什么是ou