![在 shell 脚本中生成 JSON](https://linux22.com/image/217875/%E5%9C%A8%20shell%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E7%94%9F%E6%88%90%20JSON.png)
我需要生成 JSON 输出,如下所示:
[{
"Service": "service1-name",
"AWS Account": "service1-dev",
"AD Accounts": {
"APP-Service1-Admin": ["a", "b"],
"APP-Service1-View": ["c", "d"]
}
}
]
我正在尝试这个 shell 脚本,但无法插入内部信息
#!/bin/bash
innerAD=$(jq -n --arg aaaa aaaa \
--arg xxxx "xxxx" \
'$ARGS.named'
)
inner=$(jq -n --argjson "APP-Service1-Admin" "[$innerAD]" \
'$ARGS.named'
)
final=$(jq -n --arg Service "service1-name" \
--arg "AWS Account" "service1-dev" \
--argjson "AD Accounts" "[$inner]" \
'$ARGS.named'
)
echo "$final"
答案1
一种建议是使用--args
withjq
创建两个数组,然后将它们收集到主文档中的正确位置。请注意,这--args
必须是命令行上的最后一个选项,并且全部其余的命令行参数将成为$ARGS.positional
数组的元素。
{
jq -n --arg key APP-Service1-Admin '{($key): $ARGS.positional}' --args a b
jq -n --arg key APP-Service1-View '{($key): $ARGS.positional}' --args c d
} |
jq -s --arg key 'AD Accounts' '{($key): add}' |
jq --arg Service service1-name --arg 'AWS account' service1-dev '$ARGS.named + .'
前两次jq
调用创建一组两个 JSON 对象:
{
"APP-Service1-Admin": [
"a",
"b"
]
}
{
"APP-Service1-View": [
"c",
"d"
]
}
第三次jq
调用用于-s
将该集合读入数组,该数组在传递时成为合并对象add
。合并的对象被分配给我们的顶级键:
{
"AD Accounts": {
"APP-Service1-Admin": [
"a",
"b"
],
"APP-Service1-View": [
"c",
"d"
]
}
}
最后jq
将剩余的顶级键及其值添加到对象中:
{
"Service": "service1-name",
"AWS account": "service1-dev",
"AD Accounts": {
"APP-Service1-Admin": [
"a",
"b"
],
"APP-Service1-View": [
"c",
"d"
]
}
}
和jo
:
jo -d . \
Service=service1-name \
'AWS account'=service1-dev \
'AD Accounts.APP-Service1-Admin'="$(jo -a a b)" \
'AD Accounts.APP-Service1-View'="$(jo -a c d)"
“内部”对象是使用.
-notation(通过 启用-d .
)和几个用于创建数组的命令替换来创建的。
或者您可以删除-d .
并使用数组表示法的形式:
jo Service=service1-name \
'AWS account'=service1-dev \
'AD Account[APP-Service1-Admin]'="$(jo -a a b)" \
'AD Account[APP-Service1-View]'="$(jo -a c d)"
答案2
在 bash 中创建复杂的 json 对象时,我经常使用heredocs:
service=$(thing-what-gets-service)
account=$(thing-what-gets-account)
admin=$(jo -a $(thing-what-gets-admin))
view=$(jo -a $(thing-what-gets-view))
read -rd '' json <<EOF
[
{
"Service": "$service",
"AWS Account": "$account",
"AD Accounts": {
"APP-Service1-Admin": $admin,
"APP-Service1-View": $view
}
}
]
EOF
这用于jo
创建数组,因为这是一种非常简单的方法,但如果需要,可以以不同的方式完成。
答案3
另一个jo
答案:
# 2 shell arrays
admins=("a" "b")
views=("c" "d")
accounts=$(jo "${admins[@]/#/APP_Service1-Admin[]=}" "${views[@]/#/APP_Service1-View[]=}")
final=$(jo "Service=service1-name" "AWS Account=service1-dev" "AD Accounts=$accounts")
echo "$final" | jq .
{
"Service": "service1-name",
"AWS Account": "service1-dev",
"AD Accounts": {
"APP_Service1-Admin": [
"a",
"b"
],
"APP_Service1-View": [
"c",
"d"
]
}
}
这是棘手的一点:"${admins[@]/#/APP_Service1-Admin[]=}"
$ printf '%s\n' "${admins[@]/#/APP_Service1-Admin[]=}"
APP_Service1-Admin[]=a
APP_Service1-Admin[]=b
这使您可以从 shell 数组构建一个列表。
答案4
xo(1)是在命令行上生成 JSON 的一个很棒的实用程序。它来自于libxo由瞻博网络开发的项目。方便的是,它已预安装在FreeBSD 自 11.0-RELEASE 起并可以输出 JSON 和 XML 等其他格式。这是许多 FreeBSD 管理工具使用的机制(例如,附注(1))以支持机器友好的输出格式。
以下是手册页的输出示例。
$ xo --style text "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
The fish weighs 6 pounds.
$ xo --style xml "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
<name>fish</name>
<weight>6</weight>
$ xo --style json "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
"name": "fish",
"weight": 6
"name": "fish",
$ xo --style html "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
<div class="line">
<div class="text">The </div>
<div class="data" data-tag="name">fish</div>
<div class="text"> weighs </div>
<div class="data" data-tag="weight">6</div>
<div class="text"> pounds.</div>
</div>