无法让jq识别json文件中的数组

时间:2017-09-19 14:34:01

标签: arrays json jq

我有一个用于工作的json文件,我需要解析它的格式如下:

(^)#(^)#(^)#(^)bminter@ubuntu:~$ cat jqtest
{
   "files":[
      {
         "BLOCK1":{
            "SUBBLOCK1":{
               "akey1":"avalue1",
               "bkey1":"bvalue1",
               "ckey1":"cvalue1"
            },
            "dkey1":"dvalue1",
            "key":"evalue1"
         }
      },
      {
         "BLOCK-2":{
            "SUBBLOCK2":{
               "akey2":"avalue2",
               "bkey2":"bvalue2"
            },
            "ckey2":"cvalue2",
            "key":"dvalue2"
         }
      },
      {
         "BLOCK-A":{
            "SUBBLOCK2":{
               "akey2":"avalue2",
               "bkey2":"bvalue2"
            },
            "ckey2":"cvalue2",
            "key":"dvalue2"
         }
      }],
   "NOBLOCK":"value",
   "key":"NOBLOCKvalue"
}

所以这是一个嵌套在json文件中的数组。 jq .[] jqtest为我提供了文件中的所有内容。甚至是阵列外的数据。除了数组之外,我只给出了值而不是键:

(^)#(^)#(^)#(^)bminter@ubuntu:~$ jq .[] jqtest
[
  {
    "BLOCK1": {
      "SUBBLOCK1": {
        "akey1": "avalue1",
        "bkey1": "bvalue1",
        "ckey1": "cvalue1"
      },
      "dkey1": "dvalue1",
      "key": "evalue1"
    }
  },
  {
    "BLOCK-2": {
      "SUBBLOCK2": {
        "akey2": "avalue2",
        "bkey2": "bvalue2"
      },
      "ckey2": "cvalue2",
      "key": "dvalue2"
    }
  },
  {
    "BLOCK-A": {
      "SUBBLOCK2": {
        "akey2": "avalue2",
        "bkey2": "bvalue2"
      },
      "ckey2": "cvalue2",
      "key": "dvalue2"
    }
  }
]
"value"
"NOBLOCKvalue"
(^)#(^)#(^)#(^)bminter@ubuntu:~$ 

除此之外,我无法访问数组中的任何块:

(^)#(^)#(^)#(^)bminter@ubuntu:~$ jq '.[].BLOCK1' jqtest
jq: error (at jqtest:36): Cannot index array with string "BLOCK1"
(^)#(^)#(^)#(^)bminter@ubuntu:~$ jq '.[].BLOCK-2' jqtest
jq: error (at jqtest:36): Cannot index array with string "BLOCK"
(^)#(^)#(^)#(^)bminter@ubuntu:~$ jq '.[].BLOCK-A' jqtest
jq: error: A/0 is not defined at <top-level>, line 1:
.[].BLOCK-A          
jq: 1 compile error
(^)#(^)#(^)#(^)bminter@ubuntu:~$ 

如何访问阵列?

1 个答案:

答案 0 :(得分:1)

具有非统一键的对象数组使得这里的事情变得有点棘手。一旦超过.files,您需要开始使用Array Iteration []来访问这些元素,然后使用keys之类的对象操作来深入了解。

这是一个可能有助于这种情况的功能。它会扫描.files一个具有与指定键匹配的键的对象,然后返回相应的值:

def getfile($k): .files[] | select(keys[] | .==$k) | .[$k];

如果jqtest包含示例数据命令

$ jq -M '
def getfile($k): .files[] | select(keys[] | .==$k) | .[$k];
getfile("BLOCK1").SUBBLOCK1.akey1
' jqtest

返回

"avalue1"

另一种方法是使用函数将.files[]转换为更有用的形式。 e.g。

$ jq -M '
def files: reduce .files[] as $f ({}; ($f|keys[0]) as $k | .[$k] = $f[$k]) ;
files 
' jqtest

这会返回一个没有数组的更统一的结构

{
  "BLOCK1": {
    "SUBBLOCK1": {
      "akey1": "avalue1",
      "bkey1": "bvalue1",
      "ckey1": "cvalue1"
    },
    "dkey1": "dvalue1",
    "key": "evalue1"
  },
  "BLOCK-2": ...

所以用它可以写

files.BLOCK1.SUBBLOCK1

获取

{
  "akey1": "avalue1",
  "bkey1": "bvalue1",
  "ckey1": "cvalue1"
}

请注意,jq会在每次使用时重新评估files函数,因此以下表单可能更实用:

  files as $files
| $files.BLOCK1.SUBBLOCK1

如果您发现此表示有用,则可能需要跳过该功能,而只需使用

启动过滤器
.files = reduce .files[] as $f ({}; ($f|keys[0]) as $k | .[$k] = $f[$k])

e.g。

$ jq -M '
.files = reduce .files[] as $f ({}; ($f|keys[0]) as $k | .[$k] = $f[$k])
# more stuff goes here
' jqtest

将您的输入转换为

{
  "files": {
    "BLOCK1": {
      "SUBBLOCK1": {
        "akey1": "avalue1",
        "bkey1": "bvalue1",
        "ckey1": "cvalue1"
      },
      "dkey1": "dvalue1",
      "key": "evalue1"
    },
    "BLOCK-2": {
      "SUBBLOCK2": {
        "akey2": "avalue2",
        "bkey2": "bvalue2"
      },
      "ckey2": "cvalue2",
      "key": "dvalue2"
    },
    "BLOCK-A": {
      "SUBBLOCK2": {
        "akey2": "avalue2",
        "bkey2": "bvalue2"
      },
      "ckey2": "cvalue2",
      "key": "dvalue2"
    }
  },
  "NOBLOCK": "value",
  "key": "NOBLOCKvalue"
}

在那之后做出你需要做的其他事情