简体   繁体   中英

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. 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. 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.

Some commands I've tried with the errors I get…

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

Cannot iterate over null (null)

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

Cannot iterate over string ("feature")

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

Cannot index string with string "style"

new.json file looks like this...

{
  "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 targeted approach, illustrated in an answer to your previous question at Manipulating a JSON file with jq

  • the global approach, that ignores the specific context.

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.

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. At any rate, here is a solution that uses the --stream option:

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.

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:

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 "

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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