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

Posted

技术标签:

【中文标题】使用 jq 从 JSON 对象中删除键:值【英文标题】:Remove a key:value from an JSON object using jq 【发布时间】:2018-01-30 19:21:25 【问题描述】:

我正在尝试使用 jq 从 JSON 对象中添加和删除“键:值”。我是使用 jq 的新手,我不明白 jq 向我抛出的错误,因此非常感谢任何帮助我朝着正确方向前进的帮助。我的具体问题是我有一个 JSON 对象(如下),我希望能够从 JSON 对象中添加/删除“maxHeight”键/值。

我尝试了一些命令,但出现了错误……

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

无法遍历 null (null)

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

无法遍历字符串(“特征”)

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": "(featurename)",
      "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"

【问题讨论】:

【参考方案1】:

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

jq 'del(.maxHeight)' new.json

【讨论】:

你的意思是echo ' "a": 1, "b": 2 ' | jq 'del(.a)' &gt;output.jsonecho ' "a": 1, "b": 2 ' &gt;input.json; jq 'del(.a)' input.json &gt;output.jsonecho ' "a": 1, "b": 2 ' &gt;input.json; jq 'del(.a)' input.json | sponge input.jsonsponge来自moreutils【参考方案2】:

有两种方法:

有针对性的方法,在 Manipulating a JSON file with jqManipulating a JSON file with jq上一个问题的回答中说明了这一点

全局方法,忽略特定上下文。

以下说明了全局方法:

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

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

如果您的 jq 没有 walk/1,只需在调用它之前包含其 def(例如来自 https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq)。

【讨论】:

很抱歉问了一个愚蠢的问题,但是到底如何“在调用它之前包含它的 def”?我正在使用来自 bash 的 jq,不知道该把函数放在哪里 @Sebas 看到我的回答【参考方案3】:

对于非常大的 JSON 文档,最好使用 jq 的“流解析器”来解决这类问题,至少在编辑操作大大减小文档大小的情况下。无论如何,这是一个使用 --stream 选项的解决方案:

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

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

【讨论】:

【参考方案4】:

这是一个从 Electrum Wallet JSON 文件中删除几个密钥的示例,它在 zsh 和 bash 中使用 jq 版本进行了测试,没有内置 walk

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 文件就足够了【参考方案5】:

我有类似的问题,但不想为此编写大量代码或花费太多时间。

我假设您解决了这个问题的原因。但对我来说,以下内容适用于我不必递归查找的值,即仅在顶层。另外,我不在乎是否存在空白/空值:

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

【讨论】:

以上是关于使用 jq 从 JSON 对象中删除键:值的主要内容,如果未能解决你的问题,请参考以下文章

sh 使用jq从多个JSON文件的“对象”键合并数组

使用 jq 保留键名展平 JSON

如何删除json对象键和值。?

如何按名称过滤键,然后使用 jq 访问嵌套对象

如何使用 jq 从 JSON 中获取键名

使用 jq 一次删除多个键