【发布时间】:2020-10-05 17:32:31
【问题描述】:
我有一个如下的json文件,需要将新名称附加到.root.application.names,但是如果传入的名称有前缀(-之前的所有内容,在下面的示例中是jr),然后找到列表已经存在相同的前缀名称,并更新它,如果只有一个名称列表或没有匹配的列表,则更新第一个列表。
在下面的例子中,如果
$application == 'application1' and $name == <whatever>; just update first list under application1, as there is only one list under application1, nothing to choose from.
$application == 'application2' and if $name has no prefix delimiter "-" or unmatched prefix (say sr-allen); then update the first list under application2.names, because foo has no or unmatched prefix.
$application == 'application2' and say $name == jr-allen; then update the second list under application2, because $name has prefix "jr-" and there is a list with items matching this prefix.
{
"root": {
"application1": [
{
"names": [
"john"
],
"project": "generic"
}
],
"application2": [
{
"names": [
"peter",
"jack"
],
"project": "generic"
},
{
"names": [
"jr-sam",
"jr-mike",
"jr-rita"
],
"project": "junior-project"
}
]
}
}
我找到了如何更新列表,不知道如何添加这些条件,请帮助?
jq '."root"."application2"[1].names[."root"."application2"[1].names| length] |= . + "jr-allen"' foo.json
更新: 如果我能用 jq/walk 做到这一点很好,我仍在尝试如下,但无法接近。
prefix=$(echo ${name} | cut -d"-" -f1) # this gives the prefix, e.g: "jr"
jq -r --arg app "${application}" name "${name}" prefix "${prefix}"'
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
walk( if type=="object" and ."$app" and (.names[]|startswith("$prefix")) ) then .names[]="$name" else . end )
' foo.json
【问题讨论】: