jq merge json 通过动态子键
jq merge json via dynamic sub keys
我想我离弄清楚如何将一个键 reduce via filter 转换为另一个对象的子键还有一步。
我正在尝试合并文件(根据 Elasticsearch 的 ILM Explain & ILM Policy API 响应进行了简化):
$ echo '{".siem-signals-default": {"modified_date": "siem", "version": 1 }, "kibana-event-log-policy": {"modified_date": "kibana", "version": 1 } }' > ip1.json
$ echo '{"indices": {".siem-signals-default-000001": {"action": "complete", "index": ".siem-signals-default-000001", "policy" : ".siem-signals-default"} } }' > ie1.json
结果 JSON 是:
{
".siem-signals-default-000001": {
"modified_date": "siem",
"version": 1
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default"
}
}
其中 ie1 是基础 JSON 并且对于子对象,其子元素 policy
应与 ip1 的键对齐并将其子元素复制到自身中。我一直在尝试从外部来源构建 this, this, and this (from Whosebug, also this, this, this)。我将列出以这些为基础的各种兔子洞尝试,但它们都不够:
$ ((cat ie1.json | jq '.indices') && cat ip1.json) | jq -s 'map(to_entries)|flatten|from_entries' | jq '. as $v| reduce keys[] as $k({}; if true then .[$k] += $v[$k] else . end)'
{
".siem-signals-default": {
"modified_date": "siem",
"version": 1
},
".siem-signals-default-000001": {
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default"
},
"kibana-event-log-policy": {
"modified_date": "kibana",
"version": 1
}
}
$ jq --slurpfile ip1 ip1.json '.indices as $ie1|$ie1+{ilm: $ip1 }' ie1.json
{
".siem-signals-default-000001": {
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default"
},
"ilm": [
{
".siem-signals-default": {
"modified_date": "siem",
"version": 1
},
"kibana-event-log-policy": {
"modified_date": "kibana",
"version": 1
}
}
]
}
我也期待这样的东西能工作,但它编译错误
$ jq -s ip1 ip1.json '. as $ie1|$ie1 + {ilm:(keys[] as $k; $ip1 | select(.policy == $ie1[$k]) | $ie1[$k] )}' ie1.json
jq: error: ip1/0 is not defined at <top-level>, line 1:
ip1
jq: 1 compile error
从这里您可以看到,我已经确定了加入单独文件的各种方法,但是尽管我有我认为可以用于过滤的代码,但它不正确/不生效。有谁知道如何让过滤器部分工作? TIA
这假设您正在尝试将存储在 ie1.json
中的 .indices
对象与存储在 ip1.json
中的对象中的对象组合。由于要匹配的键不同,我进一步假设您想要匹配 .indices
对象中的字段名称,通过切断最后一个破折号 -
之后的所有内容来减少相同的键在来自 ip1.json
.
的对象中
为此,ip1.json
从 input
读入为 $ip
(或者您可以为此使用 jq --argfile ip ip1.json
),然后 .indices
对象取自第一个输入 ie1.json
并向通过 with_entries(.value …)
访问的内部对象添加匹配时 $ip
内的查找结果,并相应地减少 .key
.
jq '
input as $ip | .indices | with_entries(.value += $ip[.key | sub("-[^-]*$";"")])
' ie1.json ip1.json
{
".siem-signals-default-000001": {
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default",
"modified_date": "siem",
"version": 1
}
}
如果您希望将字段 .index
的内容作为参考(在您的示例数据中具有相同的值)而不是 .indices
对象的内部字段 nane,您可以使用 map_values
而不是 with_entries
,因为您不再需要该字段的名称。
jq '
input as $ip | .indices | map_values(. += $ip[.index | sub("-[^-]*$";"")])
'ie1.json ip1.json
注意:我使用 sub
和正则表达式来操作键名,如果实际上它更复杂,您可以根据自己的喜好轻松调整。但是,如果该模式实际上就像在最后一个破折号之后切断一样简单,那么使用 .[:rindex("-")]
也可以完成工作。
我还收到了一个简单的“适用于我的用例”但不是确切答案的离线反馈:
$ jq '.indices | map(. * input[.policy])' ie1.json ip1.json
[
{
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default",
"modified_date": "siem",
"version": 1
}
]
张贴以防有人遇到类似情况,但其他答案更好。
我想我离弄清楚如何将一个键 reduce via filter 转换为另一个对象的子键还有一步。
我正在尝试合并文件(根据 Elasticsearch 的 ILM Explain & ILM Policy API 响应进行了简化):
$ echo '{".siem-signals-default": {"modified_date": "siem", "version": 1 }, "kibana-event-log-policy": {"modified_date": "kibana", "version": 1 } }' > ip1.json
$ echo '{"indices": {".siem-signals-default-000001": {"action": "complete", "index": ".siem-signals-default-000001", "policy" : ".siem-signals-default"} } }' > ie1.json
结果 JSON 是:
{
".siem-signals-default-000001": {
"modified_date": "siem",
"version": 1
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default"
}
}
其中 ie1 是基础 JSON 并且对于子对象,其子元素 policy
应与 ip1 的键对齐并将其子元素复制到自身中。我一直在尝试从外部来源构建 this, this, and this (from Whosebug, also this, this, this)。我将列出以这些为基础的各种兔子洞尝试,但它们都不够:
$ ((cat ie1.json | jq '.indices') && cat ip1.json) | jq -s 'map(to_entries)|flatten|from_entries' | jq '. as $v| reduce keys[] as $k({}; if true then .[$k] += $v[$k] else . end)'
{
".siem-signals-default": {
"modified_date": "siem",
"version": 1
},
".siem-signals-default-000001": {
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default"
},
"kibana-event-log-policy": {
"modified_date": "kibana",
"version": 1
}
}
$ jq --slurpfile ip1 ip1.json '.indices as $ie1|$ie1+{ilm: $ip1 }' ie1.json
{
".siem-signals-default-000001": {
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default"
},
"ilm": [
{
".siem-signals-default": {
"modified_date": "siem",
"version": 1
},
"kibana-event-log-policy": {
"modified_date": "kibana",
"version": 1
}
}
]
}
我也期待这样的东西能工作,但它编译错误
$ jq -s ip1 ip1.json '. as $ie1|$ie1 + {ilm:(keys[] as $k; $ip1 | select(.policy == $ie1[$k]) | $ie1[$k] )}' ie1.json
jq: error: ip1/0 is not defined at <top-level>, line 1:
ip1
jq: 1 compile error
从这里您可以看到,我已经确定了加入单独文件的各种方法,但是尽管我有我认为可以用于过滤的代码,但它不正确/不生效。有谁知道如何让过滤器部分工作? TIA
这假设您正在尝试将存储在 ie1.json
中的 .indices
对象与存储在 ip1.json
中的对象中的对象组合。由于要匹配的键不同,我进一步假设您想要匹配 .indices
对象中的字段名称,通过切断最后一个破折号 -
之后的所有内容来减少相同的键在来自 ip1.json
.
为此,ip1.json
从 input
读入为 $ip
(或者您可以为此使用 jq --argfile ip ip1.json
),然后 .indices
对象取自第一个输入 ie1.json
并向通过 with_entries(.value …)
访问的内部对象添加匹配时 $ip
内的查找结果,并相应地减少 .key
.
jq '
input as $ip | .indices | with_entries(.value += $ip[.key | sub("-[^-]*$";"")])
' ie1.json ip1.json
{
".siem-signals-default-000001": {
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default",
"modified_date": "siem",
"version": 1
}
}
如果您希望将字段 .index
的内容作为参考(在您的示例数据中具有相同的值)而不是 .indices
对象的内部字段 nane,您可以使用 map_values
而不是 with_entries
,因为您不再需要该字段的名称。
jq '
input as $ip | .indices | map_values(. += $ip[.index | sub("-[^-]*$";"")])
'ie1.json ip1.json
注意:我使用 sub
和正则表达式来操作键名,如果实际上它更复杂,您可以根据自己的喜好轻松调整。但是,如果该模式实际上就像在最后一个破折号之后切断一样简单,那么使用 .[:rindex("-")]
也可以完成工作。
我还收到了一个简单的“适用于我的用例”但不是确切答案的离线反馈:
$ jq '.indices | map(. * input[.policy])' ie1.json ip1.json
[
{
"action": "complete",
"index": ".siem-signals-default-000001",
"policy": ".siem-signals-default",
"modified_date": "siem",
"version": 1
}
]
张贴以防有人遇到类似情况,但其他答案更好。