使用jq仅将JSON文件中的某些属性传输或合并到另一个JSON文件中

ih99xse1  于 2023-02-10  发布在  其他
关注(0)|答案(2)|浏览(147)

我有两个JSON文件:

$ jq . a.json b.json 
{
  "id": "ZGVhZGJlZWY=",
  "name": "first file",
  "version": 1,
  "description": "just a simple json file"
}
{
  "version": 2,
  "name": "fake name",
  "dependencies": [
    4,
    2
  ],
  "comment": "I'm just sitting here, ignore me"
}

想把它们合并成一个文件(将文件1视为"模板",将文件2视为"实际值")。我不想合并所有属性,我只想传输第二个文件的一些属性(特别是仅versiondependencies)。version应覆盖原始文件中的值,dependencies应添加到新文件中。不能覆盖name,并且必须保留原始名称。
这是预期结果:

{
  "id": "ZGVhZGJlZWY=",
  "name": "first file",
  "version": 2,
  "description": "just a simple json file",
  "dependencies": [
    4,
    2
  ]
}

我知道jq支持+*操作符来合并或递归合并,但是我怎样才能将这些操作符只应用于某些属性而不是全部属性呢?我是否必须预处理文件,然后在第二次jq调用中使用--arg
显然,jq '. + {version, dependencies}' a.json b.json不起作用。这里正确的程序是什么?
如果description也应该从输出中删除,解决方案会是什么样子?

gblwokeq

gblwokeq1#

如果您想要简单、简短和高效,请考虑:

jq '. + (input|{version, dependencies})' a.json b.json

如果第一个文件可能具有.dependencies,并且在这种情况下要添加第二个文件的:

jq '. as $a | input as $b | $a + ($b|{version}) | .dependencies += $b.dependencies'

要删除.description,可以将| del(.description)附加到这两个过滤器中的任何一个。

xwbd5t1u

xwbd5t1u2#

这里可以使用+*,这是正确的。让我们先看看+是如何工作的:

$ jq -n '{a:1,b:2} + {b:3,c:4}'
{
  "a": 1,
  "b": 3,
  "c": 4
}
  • 仅保留左侧对象中存在的属性
  • 右侧对象的属性将覆盖左侧对象的属性
  • 添加仅存在于右侧对象中的属性

很好,现在如何从两个不相关的文件中获取对象?可以使用--slurpfile,它将文件中的所有JSON实体读入一个数组,并将其放入一个变量中。

$ jq --slurpfile b b.json '. + $b[0]' a.json
{
  "id": "ZGVhZGJlZWY=",
  "name": "fake name",
  "version": 2,
  "description": "just a simple json file",
  "dependencies": [
    4,
    2
  ],
  "comment": "I'm just sitting here, ignore me"
}

我们越来越接近,但还没有完全达到。name被覆盖,comment被添加;为了解决这个问题,我们可以把吃东西的对象转换成一个只包含我们所关心的属性的新对象

$ jq --slurpfile b b.json '. + ($b[0] | {version,dependencies})' a.json
{
  "id": "ZGVhZGJlZWY=",
  "name": "first file",
  "version": 2,
  "description": "just a simple json file",
  "dependencies": [
    4,
    2
  ]
}

现在让我们回答问题的第二部分:“可以删除第一个文件的某些属性吗?”
基本上有两种选择:
1.创建一个只包含所需属性的新对象,然后添加第二个对象(可以忽略第二个文件的任何属性部分,因为无论如何都会添加它):{id,name} + ($b[0] | {version,dependencies})
1.正在删除不需要的属性:del(.description) + ($b[0] | {version,dependencies}). + ($b[0] | {version,dependencies}) | del(.description)
根据要保留/删除的属性的数量,一个或另一个解决方案可能更易于使用。创建新对象的优点是能够一次重命名属性。
执行方案二:

$ jq --slurpfile b b.json 'del(.description) + ($b[0] | {version,dependencies})' a.json
{
  "id": "ZGVhZGJlZWY=",
  "name": "first file",
  "version": 2,
  "dependencies": [
    4,
    2
  ]
}

相关问题