使用 JQ 创建新对象,其中键来自一个对象,值来自另一个对象
Use JQ to create new object where the key comes from one object and the value comes from another
我有以下输入:
{
"Columns": [
{
"email": 123,
"name": 456,
"firstName": 789,
"lastName": 450,
"admin": 900,
"licensedSheetCreator": 617,
"groupAdmin": 354,
"resourceViewer": 804,
"id": 730,
"status": 523,
"sheetCount": 298
}
]
}
{
"Users": [
{
"email": "abc@def.com",
"name": "Abc Def",
"firstName": "Abc",
"lastName": "Def",
"admin": false,
"licensedSheetCreator": true,
"groupAdmin": false,
"resourceViewer": true,
"id": 521,
"status": "ACTIVE",
"sheetCount": 0
},
{
"email": "aaa@bbb.com",
"name": "Aaa Bob",
"firstName": "Aaa",
"lastName": "Bob",
"admin": false,
"licensedSheetCreator": true,
"groupAdmin": false,
"resourceViewer": false,
"id": 352,
"status": "ACTIVE",
"sheetCount": 0
}
]
}
我需要更改用户中所有键值对的键以匹配列中的值,如下所示:
{
"Columns": [
{
"email": 123,
"name": 456,
"firstName": 789,
"lastName": 450,
"admin": 900,
"licensedSheetCreator": 617,
"groupAdmin": 354,
"resourceViewer": 804,
"id": 730,
"status": 523,
"sheetCount": 298
}
]
}
{
"Users": [
{
123: "abc@def.com",
456: "Abc Def",
789: "Abc",
450: "Def",
900: false,
617: true,
354: false,
804: true,
730: 521,
523: "ACTIVE",
298: 0
},
{
123: "aaa@bbb.com",
456: "Aaa Bob",
789: "Aaa",
450: "Bob",
900: false,
617: true,
354: false,
804: false,
730: 352,
523: "ACTIVE",
298: 0
}
]
}
我不介意更新用户数组或创建新的对象数组。
我尝试了几种组合,包括条目、条目、条目、尝试使用变量搜索键,但我越深入,就越困惑。
流的元素是独立处理的。所以我们必须改变输入。
我们可以将流元素分组到一个数组中。对于输入流,这可以使用 --slurp
/-s
.[1]
来实现
jq -s '
( .[0].Columns[0] | map_values( tostring ) ) as $map |
(
.[0],
(
.[1:][] |
.Users[] |= with_entries(
.key = $map[ .key ]
)
)
)
'
Demo 在 jqplay
或者,我们可以使用 --null-input
/-n
结合 input
and/or inputs
来读取输入。
jq -n '
input |
( .Columns[0] | map_values( tostring ) ) as $map |
(
.,
(
inputs |
.Users[] |= with_entries(
.key = $map[ .key ]
)
)
)
'
Demo 在 jqplay
请注意,您想要的输出无效 JSON。对象键必须是字符串。所以上面生成的文档与请求的文档略有不同。
请注意,我假设 .Columns
始终是一个只有一个元素的数组。这是一个无意义的假设,但这是问题有意义的唯一方式。
- 对于代码生成的流,您可以将流生成器放在数组构造函数中 (
[]
)。 reduce
也可用于从流中收集。例如,map( ... )
可以写成 [ .[] | ... ]
和 reduce .[] as $_ ( []; . + [ $_ | ... ] )
.
以下虽然没有对键进行排序,但具有简单的优点。
它假设 jq 是用 -n 选项调用的,当然会产生一个有效的 JSON 对象流:
input
| . as $Columns
| .Columns[0] as $dict
| input # Users
| .Users[] |= with_entries(.key |= ($dict[.]|tostring))
| $Columns, .
如果对键进行排序很重要,那么您可以轻松地添加合适的代码来做到这一点;或者,如果您不介意对所有对象的键进行排序,则可以使用 -S command-line 选项。
我有以下输入:
{
"Columns": [
{
"email": 123,
"name": 456,
"firstName": 789,
"lastName": 450,
"admin": 900,
"licensedSheetCreator": 617,
"groupAdmin": 354,
"resourceViewer": 804,
"id": 730,
"status": 523,
"sheetCount": 298
}
]
}
{
"Users": [
{
"email": "abc@def.com",
"name": "Abc Def",
"firstName": "Abc",
"lastName": "Def",
"admin": false,
"licensedSheetCreator": true,
"groupAdmin": false,
"resourceViewer": true,
"id": 521,
"status": "ACTIVE",
"sheetCount": 0
},
{
"email": "aaa@bbb.com",
"name": "Aaa Bob",
"firstName": "Aaa",
"lastName": "Bob",
"admin": false,
"licensedSheetCreator": true,
"groupAdmin": false,
"resourceViewer": false,
"id": 352,
"status": "ACTIVE",
"sheetCount": 0
}
]
}
我需要更改用户中所有键值对的键以匹配列中的值,如下所示:
{
"Columns": [
{
"email": 123,
"name": 456,
"firstName": 789,
"lastName": 450,
"admin": 900,
"licensedSheetCreator": 617,
"groupAdmin": 354,
"resourceViewer": 804,
"id": 730,
"status": 523,
"sheetCount": 298
}
]
}
{
"Users": [
{
123: "abc@def.com",
456: "Abc Def",
789: "Abc",
450: "Def",
900: false,
617: true,
354: false,
804: true,
730: 521,
523: "ACTIVE",
298: 0
},
{
123: "aaa@bbb.com",
456: "Aaa Bob",
789: "Aaa",
450: "Bob",
900: false,
617: true,
354: false,
804: false,
730: 352,
523: "ACTIVE",
298: 0
}
]
}
我不介意更新用户数组或创建新的对象数组。 我尝试了几种组合,包括条目、条目、条目、尝试使用变量搜索键,但我越深入,就越困惑。
流的元素是独立处理的。所以我们必须改变输入。
我们可以将流元素分组到一个数组中。对于输入流,这可以使用 --slurp
/-s
.[1]
jq -s '
( .[0].Columns[0] | map_values( tostring ) ) as $map |
(
.[0],
(
.[1:][] |
.Users[] |= with_entries(
.key = $map[ .key ]
)
)
)
'
Demo 在 jqplay
或者,我们可以使用 --null-input
/-n
结合 input
and/or inputs
来读取输入。
jq -n '
input |
( .Columns[0] | map_values( tostring ) ) as $map |
(
.,
(
inputs |
.Users[] |= with_entries(
.key = $map[ .key ]
)
)
)
'
Demo 在 jqplay
请注意,您想要的输出无效 JSON。对象键必须是字符串。所以上面生成的文档与请求的文档略有不同。
请注意,我假设 .Columns
始终是一个只有一个元素的数组。这是一个无意义的假设,但这是问题有意义的唯一方式。
- 对于代码生成的流,您可以将流生成器放在数组构造函数中 (
[]
)。reduce
也可用于从流中收集。例如,map( ... )
可以写成[ .[] | ... ]
和reduce .[] as $_ ( []; . + [ $_ | ... ] )
.
以下虽然没有对键进行排序,但具有简单的优点。 它假设 jq 是用 -n 选项调用的,当然会产生一个有效的 JSON 对象流:
input
| . as $Columns
| .Columns[0] as $dict
| input # Users
| .Users[] |= with_entries(.key |= ($dict[.]|tostring))
| $Columns, .
如果对键进行排序很重要,那么您可以轻松地添加合适的代码来做到这一点;或者,如果您不介意对所有对象的键进行排序,则可以使用 -S command-line 选项。