使用 jq 在特定行之前附加 json 块

使用 jq 在特定行之前附加 json 块

我有一个场景,我已经有一个 json 文件,我想使用 jq 打开和编辑该文件。

json 文件(temp.json):

{
  "a":{
    "keya" : "abc",
    "keyb" : "xyz"
  },
  "c":{
    "keyc" : "yyy"
  }
}

在这里,我想c通过搜索在块之前附加另一个 json 对象,基本上是在最后一个对象之前附加值,在这种情况下,最后一个对象将始终是c

  "b":{
    "keyb" : "yop"
  }

我使用 jq 实现了插入块,但没有插入到所需的位置。 jq '. |= . + {"b":{ "keyb" : "yop" }}' temp.json

任何帮助都会很好

答案1

您可以使用jq-S选项对键进行排序。例如

$ jq -S '. |= . + {"b":{ "keyb" : "yop" }}' temp.json
{
  "a": {
    "keya": "abc",
    "keyb": "xyz"
  },
  "b": {
    "keyb": "yop"
  },
  "c": {
    "keyc": "yyy"
  }
}

答案2

对象是未排序的键集合。键的顺序真的应该没关系到读取 JSON 文档的应用程序。如果您想要有序数据,请考虑使用数组。

以下是分步解决方案。最终代码在最后。

由于数组是有序的,我们可以使用以下方法将顶级对象转换为键和值的有序数组to_entries

$ jq 'to_entries' file
[
  {
    "key": "a",
    "value": {
      "keya": "abc",
      "keyb": "xyz"
    }
  },
  {
    "key": "c",
    "value": {
      "keyc": "yyy"
    }
  }
]

我们可以在该数组的最后一个元素之前插入内容。在这里,我使用第一个元素(除了最后一个原始元素之外的所有元素.[:-1])、新元素以及最后一个原始元素(.[-1])的切片来重写“条目”数组。

$ jq 'to_entries | . |= .[:-1] + [ { key: "b", value: { keyb: "yop" } }, .[-1] ]' file
[
  {
    "key": "a",
    "value": {
      "keya": "abc",
      "keyb": "xyz"
    }
  },
  {
    "key": "b",
    "value": {
      "keyb": "yop"
    }
  },
  {
    "key": "c",
    "value": {
      "keyc": "yyy"
    }
  }
]

然后我们可以将其转换回其原始形式,希望from_entries不会改变键的顺序:

$ jq 'to_entries | . |= .[:-1] + [ { key: "b", value: { keyb: "yop" } }, .[-1] ] | from_entries' file
{
  "a": {
    "keya": "abc",
    "keyb": "xyz"
  },
  "b": {
    "keyb": "yop"
  },
  "c": {
    "keyc": "yyy"
  }
}

在命令行上将新元素作为键和 JSON 对象:

$ jq --arg key 'yellow' --argjson value '{ "type": "color" }' 'to_entries | . |= .[:-1] + [ { key: $key, value: $value }, .[-1] ] | from_entries' file
{
  "a": {
    "keya": "abc",
    "keyb": "xyz"
  },
  "yellow": {
    "type": "color"
  },
  "c": {
    "keyc": "yyy"
  }
}

相关内容