如何将 url 字符串引用的远程 json 合并到当前 json
How to merge a remote json referenced by a url string into the current json
给定
[
{"json1": "http://example.com/remote1.json"},
{"json2": "http://example.com/remote2.json"}
]
其中 remote1.json
和 remote2.json
分别包含 [1]
和 [2]
如何变成
[{"json1": [1], "json2": [2]}]
使用jq?我认为需要其他 CLI 工具,例如 bash 和 curl。但是我不知道如何将回复合并回来。
已提议为 jq 提供网络访问权限,但由于安全性、复杂性、可移植性和过时软件问题的某种组合而被拒绝。
同样提出了脱壳,但似乎还有一段路要走。
很容易实现什么
我理解这是这里的目标,将 jq 和 curl 与脚本语言结合使用,例如 bash。一种方法是序列化 JSON,然后在反序列化之前使用 curl "edit" 序列化的 JSON。对于 jq 中的 serialization/deserialization 函数,请参见例如How to Flatten JSON using jq and Bash into Bash Associative Array where Key=Selector?
如果要替换所有作为有效 URL 的字符串,那么识别它们原则上可以在序列化之前或之后完成。如果只取消引用此类字符串的一个子集,则选择可能取决于具体要求。
XPath/XQuery 具有网络访问功能,因为 W3C 喜欢 URI 引用。如果您对其他工具持开放态度,可以试试我的 XPath/XQuery/JSONiq interpreter:
xidel master.json -e '[$json()()!{.:json($json()(.))}]'
语法:
$json
为输入数据
json()
是检索JSON
的函数
()
是数组值或对象键
!
映射一系列值,其中 .
是单个值
首先,我们的测试框架:
curl() {
case in
http://example.com/remote1.json) echo "[1]" ;;
http://example.com/remote2.json) echo "[2]" ;;
*) echo "IMABUG" ;;
esac
}
input_json='[
{"json1": "http://example.com/remote1.json"},
{"json2": "http://example.com/remote2.json"}
]'
那么,我们的实际代码:
# defines the "walk" function, which is not yet included in a released version of jq
# ...in the future, this will not be necessary.
walk_fn='
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;
'
get_url_keys() {
jq -r "$walk_fn
walk(
if type == \"object\" then
to_entries
else . end
)
| flatten
| .[]
| select(.value | test(\"://\"))
| [.key, .value]
| @tsv"
}
operations=( )
options=( )
i=0
while IFS=$'\t' read -r key url; do
options+=( --arg "key$i" "$key" --argjson "value$i" "$(curl "$url")" )
operations+=(
" walk(
if type == \"object\" then
if .[$key$i] then .[$key$i]=$value$i else . end
else . end
) "
)
(( ++i ))
done < <(get_url_keys <<<"$input_json")
IFS='|' # separate operations with a | character
jq -c "${options[@]}" "${walk_fn} ${operations[*]}" <<<"$input_json"
输出正确:
[{"json1":[1]},{"json2":[2]}]
给定
[
{"json1": "http://example.com/remote1.json"},
{"json2": "http://example.com/remote2.json"}
]
其中 remote1.json
和 remote2.json
分别包含 [1]
和 [2]
如何变成
[{"json1": [1], "json2": [2]}]
使用jq?我认为需要其他 CLI 工具,例如 bash 和 curl。但是我不知道如何将回复合并回来。
已提议为 jq 提供网络访问权限,但由于安全性、复杂性、可移植性和过时软件问题的某种组合而被拒绝。
同样提出了脱壳,但似乎还有一段路要走。
很容易实现什么 我理解这是这里的目标,将 jq 和 curl 与脚本语言结合使用,例如 bash。一种方法是序列化 JSON,然后在反序列化之前使用 curl "edit" 序列化的 JSON。对于 jq 中的 serialization/deserialization 函数,请参见例如How to Flatten JSON using jq and Bash into Bash Associative Array where Key=Selector?
如果要替换所有作为有效 URL 的字符串,那么识别它们原则上可以在序列化之前或之后完成。如果只取消引用此类字符串的一个子集,则选择可能取决于具体要求。
XPath/XQuery 具有网络访问功能,因为 W3C 喜欢 URI 引用。如果您对其他工具持开放态度,可以试试我的 XPath/XQuery/JSONiq interpreter:
xidel master.json -e '[$json()()!{.:json($json()(.))}]'
语法:
$json
为输入数据json()
是检索JSON 的函数
()
是数组值或对象键!
映射一系列值,其中.
是单个值
首先,我们的测试框架:
curl() {
case in
http://example.com/remote1.json) echo "[1]" ;;
http://example.com/remote2.json) echo "[2]" ;;
*) echo "IMABUG" ;;
esac
}
input_json='[
{"json1": "http://example.com/remote1.json"},
{"json2": "http://example.com/remote2.json"}
]'
那么,我们的实际代码:
# defines the "walk" function, which is not yet included in a released version of jq
# ...in the future, this will not be necessary.
walk_fn='
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;
'
get_url_keys() {
jq -r "$walk_fn
walk(
if type == \"object\" then
to_entries
else . end
)
| flatten
| .[]
| select(.value | test(\"://\"))
| [.key, .value]
| @tsv"
}
operations=( )
options=( )
i=0
while IFS=$'\t' read -r key url; do
options+=( --arg "key$i" "$key" --argjson "value$i" "$(curl "$url")" )
operations+=(
" walk(
if type == \"object\" then
if .[$key$i] then .[$key$i]=$value$i else . end
else . end
) "
)
(( ++i ))
done < <(get_url_keys <<<"$input_json")
IFS='|' # separate operations with a | character
jq -c "${options[@]}" "${walk_fn} ${operations[*]}" <<<"$input_json"
输出正确:
[{"json1":[1]},{"json2":[2]}]