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

How can I pull an IPv4 address from a JSON response by seacrhing nested values?

我是 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 的父项的值。在这种情况下,当 family 等于 inet.

时,我只想将 10.0.0.20 作为输出

我在这里经历了多个问题,Google 没有帮助。我知道我需要使用 JSON.parse 解析 JSON,然后使用 maybe find 或 select 来得到我的答案,但我无法让它工作。

我不确定是否有任何其他方法可以做到这一点,就像您在 Bash 中使用 grep 或 awk 所做的那样。一种 hack 可能是使用 foo.[46..54] 之类的东西来输出 IP,但我再次认为这不是解决这个问题的好方法。

如果你想要 family inet,

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

请注意,检测将 return 一个数组。

使用哈希#invert

假设您的哈希已经使用 JSON#parse, one way to solve the problem is to invert the Hash with the Hash#invert 方法存储在 response 中。例如:

# 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. 假设 response 哈希中只有一个 IPv4 地址。如果您有多个以 inet 作为值的键,请不要使用 pop 并按您认为合适的方式处理结果数组。例如:

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

  3. 它适用于您拥有的 JSON,但不能解决任意嵌套或变化的数据结构。如果您有不同类型的输入,请考虑 "some assembly required."

  4. 如果你没有inet家庭,那么{}.values.pop可能return没有。请确保您在申请中对此进行了规划。

None 这些是您特定用例的阻碍因素,但它们确实值得牢记。您的里程可能会有所不同。