简体   繁体   English

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

[英]Remove a key:value from an JSON object using jq

I'm trying to add and remove a 'key:value' from a JSON object using jq.我正在尝试使用 jq 从 JSON 对象中添加和删除“键:值”。 I'm new using jq and I do not understand the errors that jq is throwing at me, so any help pushing me in the correct direction is greatly appreciated.我是使用 jq 的新手,我不明白 jq 向我抛出的错误,因此非常感谢将我推向正确方向的任何帮助。 My specific issue is I have a JSON object (below) and I want to be able to add/remove the “maxHeight” key/value from the JSON object.我的具体问题是我有一个 JSON 对象(如下),我希望能够从 JSON 对象中添加/删除“maxHeight”键/值。

Some commands I've tried with the errors I get…我尝试过的一些命令遇到了错误……

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

Cannot iterate over null (null)无法迭代 null (null)

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

Cannot iterate over string ("feature")无法迭代字符串(“功能”)

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

Cannot index string with string "style"不能用字符串“style”索引字符串

new.json file looks like this... 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"
}

使用 jq-1.6,这会从输入中删除键 .maxHeight(如果它以前不存在,它甚至不会抱怨):

jq 'del(.maxHeight)' new.json

There are two approaches:有两种方法:

The following illustrates the global approach:以下说明了全局方法:

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

This in effect "edits" the input by updating whichever objects have the specified key.这实际上通过更新具有指定键的任何对象来“编辑”输入。

If your jq does not have walk/1 simply include its def (available eg from https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq ) before invoking it.如果您的 jq 没有walk/1只需在调用它之前包含它的 def(例如从https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq可用)。

For very large JSON documents, it may be preferable to use jq's "streaming parser" for this kind of problem, at least if the editing operations greatly reduce the size of the document.对于非常大的 JSON 文档,对于此类问题,最好使用 jq 的“流式解析器”,至少如果编辑操作大大减小了文档的大小。 At any rate, here is a solution that uses the --stream option:无论如何,这是一个使用--stream选项的解决方案:

jq --stream 'select(length == 2 and .[0][-1] == "maxHeight" | not)' new.json |
 jq -n 'fromstream(inputs)'

Note that the -n option must be used in the second call to jq.请注意,在第二次调用 jq 时必须使用-n选项。

Here is an example removing a couple of keys from an Electrum Wallet JSON file, this was tested in zsh and bash with a verison of jq that doesn't have walk built in:这是一个从 Electrum Wallet 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

I had a similar issue, but did not want to make a lot of code for this or spend too much time on it.我有一个类似的问题,但不想为此编写大量代码或花费太多时间。

I'm assuming you fixed your reason for this.我假设你已经解决了这个原因。 But for me, the following worked for a value that I did not have to recursively look for, ie only at the top level.但对我来说,以下内容适用于我不必递归查找的值,即仅在顶层。 Also, I did not care if a blank/null value was there:另外,我不在乎是否存在空白/空值:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM