将嵌套的 json 参数变量作为键传递给 JQ json 库
Passing nested json argument variable as key to JQ json library
我有两个 JSON 文件要传递给 jq 对象,检查以下内容:
Create.json
{
"email_notifications": {
"on_failure": "_"
},
"name": "_",
"schedule": {
"quartz_cron_expression": "_",
"timezone_id": "Europe/Amsterdam",
"pause_status": "_"
}
}
Update.json
{
"job_id": "_",
"new_settings": {
"email_notifications": {
"on_failure": "_"
},
"name": "_",
"schedule": {
"quartz_cron_expression": "_",
"timezone_id": "Europe/Amsterdam",
"pause_status": "_"
}
}
对于Create.json我可以使用下面的表达式:
TEMPLATE=`cat $FILE | jq
--arg _parent "$PARENT"
--arg _job_name "$JOB_NAME"
' ( . | .name ) |= $_job_name
| ( . | .schedule.pause_status) |= $_parent'
`
for Update.json 我需要使用表达式来包含父键名:
TEMPLATE=`cat $FILE | jq
--arg _parent "$PARENT"
--arg _job_name "$JOB_NAME"
' ( .["new_settings"] | .name ) |= $_job_name
| ( .["new_settings"] | .schedule.pause_status) |= $_parent'
为了处理这个问题,我在表达式中使用了 if else,并且效果很好:
(如果 .job_id? 那么 .["new_settings"] 否则 .end | .name )|= $_job_name
但我想将初始部分作为参数传递,但它不起作用并给出语法错误。我怎样才能使参数在传递时成为运行时表达式的动态:
Filter="." OR Filter=".["new_settings"]"
TEMPLATE=`cat $FILE | jq
--arg filter "$Filter"
--arg _parent "$PARENT"
--arg _job_name "$JOB_NAME"
' ( $filter | .name ) |= $_job_name
| ( $filter | .schedule.pause_status) |= $_parent'
# --arg root_path ""
# --arg root_path "new_settings"
getpath( $root_path | split(".") ) |= (
.name = $_job_name |
.schedule.pause_status = $_parent
)
参数不应该是一段jq代码。接受一段 jq 代码传递给 eval
是一种不好的做法。但是 jq
甚至没有 eval
,所以它甚至不是一个选项。
我们可以使用 JSON 数组提供路径。
# --argjson root_path '[]'
# --argjson root_path '["new_settings"]'
getpath($root_path)
但是点分隔的路径要好得多。
# --arg root_path ""
# --arg root_path "new_settings"
getpath( $root_path | split(".") ) # Supports objects
getpath( $root_path | split(".") | map( tonumber? // . ) ) # Supports objects & arrays
这给了我们这样的东西:
getpath( $root_path | split(".") ) as $root |
( $root | .name ) |= $_job_name |
( $root | .schedule.pause_status ) |= $_parent
除非使用 $root
两次没有意义。
getpath( $root_path | split(".") ) as $root |
$root |= (
.name |= $_job_name |
.schedule.pause_status |= $_parent
)
或者只是
getpath( $root_path | split(".") ) |= (
.name |= $_job_name |
.schedule.pause_status |= $_parent
)
=
和 |=
之间的唯一区别是提供给右侧的上下文 (.
)。因此,先前存在的两个 |=
可以简化为 =
.
getpath( $root_path | split(".") ) |= (
.name = $_job_name |
.schedule.pause_status = $_parent
)
Demo on jqplay Create.json
Demo on jqplayUpdate.json
我有两个 JSON 文件要传递给 jq 对象,检查以下内容:
Create.json
{
"email_notifications": {
"on_failure": "_"
},
"name": "_",
"schedule": {
"quartz_cron_expression": "_",
"timezone_id": "Europe/Amsterdam",
"pause_status": "_"
}
}
Update.json
{
"job_id": "_",
"new_settings": {
"email_notifications": {
"on_failure": "_"
},
"name": "_",
"schedule": {
"quartz_cron_expression": "_",
"timezone_id": "Europe/Amsterdam",
"pause_status": "_"
}
}
对于Create.json我可以使用下面的表达式:
TEMPLATE=`cat $FILE | jq
--arg _parent "$PARENT"
--arg _job_name "$JOB_NAME"
' ( . | .name ) |= $_job_name
| ( . | .schedule.pause_status) |= $_parent'
`
for Update.json 我需要使用表达式来包含父键名:
TEMPLATE=`cat $FILE | jq
--arg _parent "$PARENT"
--arg _job_name "$JOB_NAME"
' ( .["new_settings"] | .name ) |= $_job_name
| ( .["new_settings"] | .schedule.pause_status) |= $_parent'
为了处理这个问题,我在表达式中使用了 if else,并且效果很好: (如果 .job_id? 那么 .["new_settings"] 否则 .end | .name )|= $_job_name
但我想将初始部分作为参数传递,但它不起作用并给出语法错误。我怎样才能使参数在传递时成为运行时表达式的动态:
Filter="." OR Filter=".["new_settings"]"
TEMPLATE=`cat $FILE | jq
--arg filter "$Filter"
--arg _parent "$PARENT"
--arg _job_name "$JOB_NAME"
' ( $filter | .name ) |= $_job_name
| ( $filter | .schedule.pause_status) |= $_parent'
# --arg root_path ""
# --arg root_path "new_settings"
getpath( $root_path | split(".") ) |= (
.name = $_job_name |
.schedule.pause_status = $_parent
)
参数不应该是一段jq代码。接受一段 jq 代码传递给 eval
是一种不好的做法。但是 jq
甚至没有 eval
,所以它甚至不是一个选项。
我们可以使用 JSON 数组提供路径。
# --argjson root_path '[]'
# --argjson root_path '["new_settings"]'
getpath($root_path)
但是点分隔的路径要好得多。
# --arg root_path ""
# --arg root_path "new_settings"
getpath( $root_path | split(".") ) # Supports objects
getpath( $root_path | split(".") | map( tonumber? // . ) ) # Supports objects & arrays
这给了我们这样的东西:
getpath( $root_path | split(".") ) as $root |
( $root | .name ) |= $_job_name |
( $root | .schedule.pause_status ) |= $_parent
除非使用 $root
两次没有意义。
getpath( $root_path | split(".") ) as $root |
$root |= (
.name |= $_job_name |
.schedule.pause_status |= $_parent
)
或者只是
getpath( $root_path | split(".") ) |= (
.name |= $_job_name |
.schedule.pause_status |= $_parent
)
=
和 |=
之间的唯一区别是提供给右侧的上下文 (.
)。因此,先前存在的两个 |=
可以简化为 =
.
getpath( $root_path | split(".") ) |= (
.name = $_job_name |
.schedule.pause_status = $_parent
)
Demo on jqplay Create.json
Demo on jqplayUpdate.json