使用 JQ 处理嵌套对象映射中的空值

Handling nulls in nested object maps with JQ

我刚学jq,有点卡在这里。假设我有一个名为 testcite.json 的文件,如下所示:

[
  {
    "id": "JoeSchmoe2020",
    "abstract": "Here's some junk",
    "author": [
      {
        "family": "Scmoe",
        "given": "Joe"
      },
      {
        "family": "Smith",
        "given": "Sally"
      }
    ],
    "title": "I wrote words!"
  },
  {
    "id": "EdithJones2020",
    "abstract": "It's an abstract",
    "author": [
      {
        "family": "Jones",
        "given": "Edith"
      },
      {
        "family": "Wilson",
        "given": "Eric"
      }
    ],
    "title": "These are more words!"
  }
]

假设我想把它转换成这样:

[
  {
    "author": [
      "Scmoe",
      "Smith"
    ],
    "title": "I wrote words!"
  },
  {
    "author": [
      "Jones",
      "Wilson"
    ],
    "title": "These are more words!"
  }
]

以下命令可以让我得到我想要的...只要没有任何空值。

cat testcite.json | jq '[.[] | {author: .author | map(.family), title}]'

但是一旦出现空值,就会爆炸。假设我改变我的 JSON:

[
  {
    "id": "JoeSchmoe2020",
    "abstract": "Here's some junk",
    "author": [
      {
        "family": "Scmoe",
        "given": "Joe"
      },
      {
        "family": "Smith",
        "given": "Sally"
      }
    ],
    "title": "I wrote words!"
  },
  {
    "id": "EdithJones2020",
    "abstract": "It's an abstract",
    "author": null,
    "title": "These are more words!"
  }
]

然后当我 运行 相同的命令时,我希望得到的是

[
  {
    "author": [
      "Scmoe",
      "Smith"
    ],
    "title": "I wrote words!"
  },
  {
    "author": [],
    "title": "These are more words!"
  }
]

(我也很乐意用 null 代替空列表)。

不幸的是,我得到了错误:

jq: error (at <stdin>:23): Cannot iterate over null (null)

我试过分散问号:

cat testcite.json | jq '[.[] | {author: .author | map(.family?), title}]' 只会产生相同的错误。

cat testcite.json | jq '[.[] | {author: .author | map(.family)?, title}]' 产生语法错误:

jq: error: syntax error, unexpected '?', expecting '}' (Unix shell quoting issues?) at <top-level>, line 1:
[.[] | {author: .author | map(.family)?, title}]
jq: 1 compile error

有什么方法可以让值提取仅明智地处理空值?

一个简单的解决方案是测试 null,例如

[.[]
 | {author, title}
 | .author |= if . then map(.family) else [] end
]

或类似的:

map({author: (.author 
              | if type == "array" 
                then map(.family) 
                else [] end),
     title} )