使用jq从JSON对象中删除一个键值对

20

我想使用 jq 给 JSON 对象添加和删除一个 'key:value' 。我是 jq 的新手,对 jq 报错不太理解,因此非常感谢能帮我指明正确方向的任何帮助。我的具体问题是我有一个 JSON 对象(如下),我想能够添加/删除该 JSON 对象中的“maxHeight”键/值。

我尝试了一些命令并遇到了错误:

jq 'recurse(.[]) |= del(.maxHeight)' new.json   

无法迭代null(null)

 jq 'recurse(.[]) |= {maxHeight}' new.json

无法迭代字符串("feature")

jq 'recurse(.[]) |= .maxHeight' new.json 

无法使用字符串“style”索引字符串

new.json文件如下所示...

{
  "style": {
    "className": "feature",
    "showLabels": false,
    "color": "function(feature, variableName, glyphObject, track){if(feature.get(\"type\") === \"CDS\"){return \"#9CFBF5\";} else if(feature.get(\"type\") === \"exon\"){return \"#43A47F\";} else if(feature.get(\"type\") === \"intron\"){return \"#E8E8E8\";} else if(feature.get(\"type\") === \"five_prime_UTR\"){return \"#F192FE\";} else if(feature.get(\"type\") === \"three_prime_UTR\"){return \"#FEC892\";} else {return \"#FF0000\";}}",
    "arrowheadClass": null,
    "featureCss": "padding:3px;"
  },
  "menuTemplate": [
    {
      "label": "View details"
    },
    {
      "label": "Highlight a gene"
    },
    {
      "iconClass": "dijitIconBookmark",
      "content": "function(track,feature,div) { window.parent.angular.element(window.frameElement).scope().specificNote( feature[2] ) }",
      "action": "contentDialog",
      "title": "(feature{name})",
      "label": "Create Note"
    }
  ],
  "hooks": {
    "modify": " function(track,feature,div){   var checkArr=[\"Reference\",\"Missing\",\"Heterozygous\",\"NonReference\"];for(var i=0;i<feature.length;i++){for(var j=0;j<checkArr.length;j++){  if( i>3) { if( feature[i] ===  checkArr[j] ) {  if(feature[i]==\"NonReference\"){div.style.backgroundColor=\"red\"}else if(feature[i]==\"Reference\"){div.style.backgroundColor=\"green\"}else if(feature[i]==\"Heterozygous\"){div.style.backgroundColor=\"orange\"}else if(feature[i]==\"Missing\"){div.style.backgroundColor=\"grey\"} }}}}} "
  },
  "key": "cucumber_ChineseLong_v2.gff3",
  "storeClass": "JBrowse/Store/SeqFeature/NCList",
  "trackType": null,
  "maxHeight": "200px",
  "urlTemplate": "tracks/cucumber_ChineseLong_v2.gff3/{refseq}/trackData.json",
  "compress": 0,
  "label": "cucumber_ChineseLong_v2.gff3",
  "type": "JBrowse/View/Track/CanvasFeatures"
}
5个回答

33
使用 jq-1.6,这将从输入中删除键 .maxHeight(即使它之前不存在,也不会抱怨):
jq 'del(.maxHeight)' new.json

你是指使用 echo '{ "a": 1, "b": 2 }' | jq 'del(.a)' >output.json 或者 echo '{ "a": 1, "b": 2 }' >input.json; jq 'del(.a)' input.json >output.json 或者 echo '{ "a": 1, "b": 2 }' >input.json; jq 'del(.a)' input.json | sponge input.jsonmoreutils 中的 sponge 吗? - milahu

6
有两种方法:
  • 有针对性的方法,见您先前问题的回答:使用jq操作JSON文件

  • 忽略具体上下文的全局方法。

以下是全局方法的示例:

walk(if type == "object" and has("maxHeight") then del(.maxHeight) else . end)

这实际上通过更新具有指定键的任何对象来“编辑”输入。

如果您的 jq 没有 walk/1,只需在调用它之前包含其定义(例如从 https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq 获取)即可。


抱歉问一个愚蠢的问题,但是如何在调用函数之前“包含它的定义”?我正在使用bash中的jq,不确定在哪里放置该函数。 - Sebas
@Sebas,请查看我的回答。 - Janus Troelsen

2

我曾经遇到类似的问题,但是不想花费太多时间写大量代码解决。

我假设你已经找到了解决方案。但对于我来说,以下方法适用于我不必递归查找的值,即仅在顶层查找。此外,我不关心是否存在空/空值:

最初的回答:

jq "if .maxHeight then .maxHeight = null else . end "

1
对于非常大的JSON文档,使用jq的“流解析器”可能更可取,至少在编辑操作大大减少文档大小的情况下是如此。无论如何,以下是一种使用--stream选项的解决方案:
jq --stream 'select(length == 2 and .[0][-1] == "maxHeight" | not)' new.json |
 jq -n 'fromstream(inputs)'

请注意,在第二次调用jq时必须使用-n选项。

1
这是一个从Electrum钱包JSON文件中删除一些密钥的示例,已在zsh和bash中测试,使用不带walk的jq版本。
jq -f <(
  curl https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq
  echo 'walk('
  for i in transactions spent_outpoints verified_tx3 txo txi addresses addr_history; do
    echo 'if type == "object" and has("'"$i"'") then del(.'"$i"') else . end |'
  done
  echo '.)'
)  ~/.electrum/testnet/wallets/default_wallet

啊,很酷,所以只需要在第一次放置jq文件就可以了。 - Sebas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接