【问题标题】:How can I get ruby's JSON to follow object references like Pry/PP?如何让 ruby​​ 的 JSON 遵循像 Pry/PP 这样的对象引用?
【发布时间】:2014-06-27 08:09:36
【问题描述】:

我已经盯着这个看了这么久,我在转圈……

我正在使用 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 的回复,我将这个猴子补丁添加到我的脚本中:

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,真的)提交给项目。

【问题讨论】:

    标签: json ruby pry rbvmomi


    【解决方案1】:

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

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

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

    对于一个数组,to_json先将所有元素转成json对象,再concat在一起,然后加上数组标记[/]

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

    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"}]
    

    【讨论】:

    • 足够好 - 我曾希望有一个魔法标志或类似的东西可以让它以与 pp 相同的方式处理这个问题,但我认为 pp 对对象有相同的要求(即它们需要一个 .pp 或他们自己的)。这已经足够了,我可以将它添加到库中并向上游提交补丁......
    • 作为对后来发现此问题的人们的跟进,我在我的代码中添加了以下猴子补丁:class RbVmomi::BasicTypes::DataObject def to_json(*args) h = self.props m = h.merge({ JSON.create_id =&gt; self.class.name }) m.to_json(*args) end end,现在我的 to_json 很好地递归下来。我会看看如何将这个(或真正的 def)提交给项目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 2018-03-23
    相关资源
    最近更新 更多