使用jq在json文件上基于子值查询父级数据(多级)

时间:2017-06-07 03:18:19

标签: json jq

我有一个ksh脚本,用于回复(使用curl)一个类似于下面的json文件:

{
  "Type1": {
    "dev": {
      "server": [
        {   "group": "APP1",    "name": "DAPP1002", "ip": "10.1.1.1" },
        {   "group": "APP2",    "name": "DAPP2001", "ip": "10.1.1.2" }
      ]
    },
    "qa": {
      "server": [
        {   "group": "APP1",    "name": "QAPP1002", "ip": "10.1.2.1" },
        {   "group": "APP2",    "name": "QAPP2001", "ip": "10.1.2.2" }
      ]
    },
    "prod": {
      "proxy": "type1.prod.proxy.mydomain.com",
      "server": [
        {   "group": "APP1",    "name": "PAPP1001", "ip": "10.1.3.1" },
        {   "group": "APP1",    "name": "PAPP1002", "ip": "10.1.3.2" },
        {   "group": "APP2",    "name": "PAPP2001", "ip": "10.1.3.3" }
      ]
    }
  },

  "Type2": {
    "dev": {
      "server": [
        {   "group": "APP8",    "name": "DAPP8002", "ip": "10.2.1.1" },
        {   "group": "APP9",    "name": "DAPP9001", "ip": "10.2.1.2" }
      ]
    },
    "qa": {
      "server": [
        {   "group": "APP8",    "name": "QAPP8002", "ip": "10.2.2.1" },
        {   "group": "APP9",    "name": "QAPP9001", "ip": "10.2.2.2" }
      ]
    },
    "prod": {
      "proxy": "type2.prod.proxy.mydomain.com",
      "server": [
        {   "group": "APP8",    "name": "PAPP8001", "ip": "10.2.3.1" },
        {   "group": "APP9",    "name": "PAPP9001", "ip": "10.2.3.2" },
        {   "group": "APP9",    "name": "PAPP9002", "ip": "10.2.3.3" }
      ]
    }
  }
}

...基于服务器名称(字段"name")我必须收集以下信息,以传递给函数:

"Type", "name", "ip", "proxy"

(请注意,"proxy"信息是可选的)

我是json的新手,我正在尝试用jq过滤,但到目前为止,我很幸运。 到目前为止我完成的是以下jq查询,当搜索“PAPP9001”

jq '.[] | .[] | select(.server[].name=="PAPP9001") | .proxy as $proxy | .server[] | {proxy: $proxy, name: .name, ip: .ip} | select(.name=="PAPP9001")' curlreturn.json

返回我:

{
  "proxy": "type2.prod.proxy.mydomain.com",
  "name": "PAPP9001",
  "ip": "10.2.3.2"
}

但:

  1. 我无法在顶级获得“类型”信息
  2. 考虑到管道数量和2个选择,我怀疑这是最有效的方法。

1 个答案:

答案 0 :(得分:2)

以编程方式检索密钥名称的一种方法是使用to_entries。例如,根据您的输入,此jq过滤器:

to_entries[]
| .key as $type
| .value[]
| .proxy as $proxy
| .server[]
| select(.name == "PAPP9001")
| { Type: $type, name, ip, proxy: $proxy }

的产率:

{
  "Type": "Type2",
  "name": "PAPP9001",
  "ip": "10.2.3.2",
  "proxy": "type2.prod.proxy.mydomain.com"
}

变体形式

例如,如果您想将这四个字段作为CSV行,那么您可以将上面过滤器的最后一行替换为:

| [$type, .name, .ip, $proxy] | @csv

有关如何使用字符串插值的信息,请参阅jq手册。