如何将url字符串引用的远程json合并到当前json

时间:2017-03-10 13:15:44

标签: json bash curl jq dereference

鉴于

[
  {"json1": "http://example.com/remote1.json"},
  {"json2": "http://example.com/remote2.json"}
]

remote1.jsonremote2.json分别包含[1][2]

如何将其变为

[{"json1": [1], "json2": [2]}]

使用jq?我认为需要其他CLI工具,如bash和curl。但我不知道如何合并回复。

3 个答案:

答案 0 :(得分:2)

XPath / XQuery具有网络访问功能,因为W3C喜欢URI引用。如果您对其他工具持开放态度,可以尝试我的XPath/XQuery/JSONiq interpreter

xidel master.json -e '[$json()()!{.:json($json()(.))}]'

语法:

  1. $json是输入数据

  2. json()是一个检索JSON

  3. 的函数
  4. ()是数组值或对象键

  5. !映射一系列值,其中.是单个值

答案 1 :(得分:0)

  1. 由于安全性,复杂性,可移植性和英国媒体报道软件问题的某种组合,已经为jq提出了网络访问但被拒绝了。

  2. 同样提出了脱壳,但似乎还有一段距离。

  3. 实现目标很容易 我理解这里是目标,使用jq和curl与脚本语言如bash结合使用。一种方法是序列化JSON,然后编辑"在反序列化之前使用curl的序列化JSON。有关jq中的序列化/反序列化功能,请参阅例如How to Flatten JSON using jq and Bash into Bash Associative Array where Key=Selector?

  4. 如果要替换所有有效URL的字符串,则原则上可以在序列化之前或之后进行识别。如果只取消引用此类字符串的子集,则选择可能取决于具体要求。

答案 2 :(得分:0)

首先,我们的测试框架:

curl() {
  case $1 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]}]