使用 JQ 中更高级别对象的值更新深层嵌套字段
Update deeply nested field with value from higher-level object in JQ
给定以下输入 JSON:
{
"version": 2,
"models": [
{
"name": "first_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": null
}
}
]
},
{
"name": "second_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": null
}
}
]
}
]
}
我如何使用 jq
将 null
(即 "compare_model"
的值)替换为 "name"
中的值key? 注意这里所说的键值对在层级上不在同一层级:前者嵌套在数组中的一个对象中,而与后者。
例如,输出文件应为:
{
"version": 2,
"models": [
{
"name": "first_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": "first_table"
}
}
]
},
{
"name": "second_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": "second_table"
}
}
]
}
]
}
FWIW,这是一些 YAML 的中间步骤(通过 yq
,jq
的 Python 包装器变体,而不是 go
变体)争论我在 DBT config files.
上做
(如果您可以用括号 and/or 将替换文本括起来而不用中断 jq
作为前缀,则会加分。:D 如果不行,不用担心——这一步我可以用另一个来做程序。)
不用多说,非常感谢您的帮助!
字段不在同一级别在这里并不重要。
.models[] |= (.tests[]."dbt_utils.equal_rowcount".compare_model = "(\(.name))")
简单解决方案的关键是使用|=
,例如
.models |=
map(.name as $name
| (.tests[]."dbt_utils.equal_rowcount".compare_model =
$name))
要将替换值括在括号中,只需添加它们:
.models |=
map("(\(.name))" as $name
| (.tests[]."dbt_utils.equal_rowcount".compare_model =
$name))
如果您希望替换以现有值为 null
为条件,您或许可以(取决于具体要求)使用 //=
.
使用 //=
和 walk
这是对这个问题的另一种看法:
.models
|= map("(\(.name))" as $name
| walk(if type=="object" and has("compare_model")
then .compare_model //= $name
else . end))
给定以下输入 JSON:
{
"version": 2,
"models": [
{
"name": "first_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": null
}
}
]
},
{
"name": "second_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": null
}
}
]
}
]
}
我如何使用 jq
将 null
(即 "compare_model"
的值)替换为 "name"
中的值key? 注意这里所说的键值对在层级上不在同一层级:前者嵌套在数组中的一个对象中,而与后者。
例如,输出文件应为:
{
"version": 2,
"models": [
{
"name": "first_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": "first_table"
}
}
]
},
{
"name": "second_table",
"tests": [
{
"dbt_utils.equal_rowcount": {
"compare_model": "second_table"
}
}
]
}
]
}
FWIW,这是一些 YAML 的中间步骤(通过 yq
,jq
的 Python 包装器变体,而不是 go
变体)争论我在 DBT config files.
(如果您可以用括号 and/or 将替换文本括起来而不用中断 jq
作为前缀,则会加分。:D 如果不行,不用担心——这一步我可以用另一个来做程序。)
不用多说,非常感谢您的帮助!
字段不在同一级别在这里并不重要。
.models[] |= (.tests[]."dbt_utils.equal_rowcount".compare_model = "(\(.name))")
简单解决方案的关键是使用|=
,例如
.models |=
map(.name as $name
| (.tests[]."dbt_utils.equal_rowcount".compare_model =
$name))
要将替换值括在括号中,只需添加它们:
.models |=
map("(\(.name))" as $name
| (.tests[]."dbt_utils.equal_rowcount".compare_model =
$name))
如果您希望替换以现有值为 null
为条件,您或许可以(取决于具体要求)使用 //=
.
使用 //=
和 walk
这是对这个问题的另一种看法:
.models
|= map("(\(.name))" as $name
| walk(if type=="object" and has("compare_model")
then .compare_model //= $name
else . end))