如何通过seacrhing嵌套值从JSON响应中提取IPv4地址?

时间:2018-01-13 23:24:31

标签: json ruby hash ip-address ipv4

我是Ruby新手,现在已经坚持了一段时间。我正在获得如下所述的JSON响应,目的是搜索子字符串,其子字符串的值是我指定的内容。

例如,我收到以下回复:

{
  "00:00:00:CC:00:CC": {
    "family": "lladdr"
  },
  "10.0.0.20": {
    "family": "inet",
    "prefixlen": "24",
    "netmask": "255.255.255.0",
    "broadcast": "10.0.0.255",
    "scope": "Global"
  },
  "ff00::f00:00ff:fff0:00f0": {
    "family": "inet6",
    "prefixlen": "64",
    "scope": "Link",
    "tags": []
  }
}

我需要获取密钥family的值等于inet的父级的值。在这种情况下,当家庭等于inet时,我只想要10.0.0.20作为输出。

我在这里遇到了多个问题,谷歌没有帮助。我知道我需要使用JSON.parse解析JSON,然后使用find或select来获取我的答案,但我无法使其正常工作。

我不确定是否有任何其他方式可以像使用grep或awk在Bash中那样做。一个黑客可能会使用foo.[46..54]这样会输出IP的东西,但我相信这将是一个解决这个问题的坏方法。

2 个答案:

答案 0 :(得分:0)

如果您想要family inet

result = JSON.parse(response)
family = result.detect { |k,v| v['family'] == 'inet' }
family[0] # 10.0.0.20

请注意,detect将返回一个数组。

答案 1 :(得分:0)

使用Hash #vertore

假设您的Hash已经使用JSON#parse存储在响应中,解决问题的一种方法是使用Hash#invert方法反转Hash。例如:

# Return an Array of IPv4, then pop the last/only String value.
response.invert.select { |h| h.values.include? 'inet' }.values.pop
#=> "10.0.0.20"

这是快速而简单的,它适用于您提供的数据。但是,有一些小问题。

注意事项

  1. 假设响应哈希中只有一个IPv4地址。如果您有多个以inet作为值的键,请不要使用pop并根据需要处理生成的数组。例如:

    response.invert.select { |h| h.values.include? 'inet' }.values
    #=> ["10.0.0.20"]
    
  2. 它假定每个顶级JSON对象的密钥是IP地址。我们并没有真正验证任何事情。

  3. 它适用于您拥有的JSON,但不能解决任意嵌套或变化的数据结构。如果您有不同类型的输入,请将其视为“需要一些装配。”

  4. 如果您没有inet个家庭,则{}.values.pop可能会返回nil。请确保在您的申请中为此做好计划。

  5. 这些都不是针对您的特定用例的显示停止,但它们当然值得记住。您的里程可能会有所不同。