如何让ruby的JSON跟随像Pry / PP这样的对象引用?

时间:2014-06-27 08:09:36

标签: json ruby pry rbvmomi

我已经盯着这看了很长时间才进入圈子......

我正在使用rbvmomi gem,而在Pry中,当我显示一个对象时,它通过显示嵌套对象的结构向下递归 - 但to_json似乎“挖掘”到某些对象中,但只是转储引用对于其他人>这是一个例子:

[24] pry(main)> g
=> [GuestNicInfo(
   connected: true,
   deviceConfigId: 4000,
   dynamicProperty: [],
   ipAddress: ["10.102.155.146"],
   ipConfig: NetIpConfigInfo(
     dynamicProperty: [],
     ipAddress: [NetIpConfigInfoIpAddress(
        dynamicProperty: [],
        ipAddress: "10.102.155.146",
        prefixLength: 20,
        state: "preferred"
      )]
   ),
   macAddress: "00:50:56:a0:56:9d",
   network: "F5_Real_VM_IPs"
 )]
[25] pry(main)> g.to_json
=> "[\"#<RbVmomi::VIM::GuestNicInfo:0x000000085ecc68>\"]"
Pry显然只是使用了一个加强的pp,虽然“pp g”让我接近我想要的东西,但我有点朝着json转向,所以我不需要自定义解析器来加载并操纵结果。

问题是 - 如何让json模块像pp一样挖掘?如果答案是“你不能” - 任何其他建议来实现目标?我没有和json结婚 - 如果我可以将数据序列化并稍后再读(没有写一些解析pp输出......可能已经存在并且我应该寻找它),那么它就全胜。

我的“真正”目标是通过rbvmomi从我们的vsphere东西中汲取大量信息,以便我可以对它进行一些网络/虚拟机分析,这就是为什么我想把它放在一台漂亮的机器上分散的格式。如果我在这里做一些愚蠢的事情并且有更简单的方法来解决这个问题 - 把它放在我身上,我并不自豪。谢谢大家的时间和关注。

更新:根据Arnie的回复,我将这个monkeypatch添加到我的脚本中:

class RbVmomi::BasicTypes::DataObject
   def to_json(*args)
      h = self.props
      m = h.merge({ JSON.create_id => self.class.name })
      m.to_json(*args)
   end
end

现在我的to_json很好地回复了。我会看到将这个(或def,真的)提交给项目。

1 个答案:

答案 0 :(得分:1)

.to_json以递归方式工作,默认行为为defined as

  

将此对象转换为字符串(调用to_s),将其转换为JSON字符串,然后返回结果。如果没有为某个对象定义特殊方法to_json,那么这是一个后备。

json库为一些常见类添加了一些实现(请查看this documentation的左侧),例如ArrayRangeDateTime

对于数组,to_json首先将所有元素转换为json对象,然后将其连接在一起,然后添加数组标记[ / ]

对于您的情况,您需要为to_jsonGuestNicInfoNetIpConfigInfo定义自定义的NetIpConfigInfoIpAddress方法。我不知道你对这三个类的实现,所以我写了一个例子来演示如何实现这个:

require 'json'

class MyClass
  attr_accessor :a, :b
  def initialize(a, b)
    @a = a
    @b = b
  end
end

data = [MyClass.new(1, "foobar")]
puts data.to_json
#=> ["#<MyClass:0x007fb6626c7260>"]    

class MyClass
  def to_json(*args)
    {
      JSON.create_id => self.class.name,
      :a => a,
      :b => b
    }.to_json(*args)
  end
end

puts data.to_json
#=> [{"json_class":"MyClass","a":1,"b":"foobar"}]