【问题标题】:Parse JSON and iterate objects using jq使用 jq 解析 JSON 和迭代对象
【发布时间】:2020-06-17 03:38:25
【问题描述】:
[ 
{ "id":"1", 
  "metadata":{"version":"1.0","author":"user1"}
},
{ "id":"2", 
  "metadata":{"version":"1.0","author":"user2","timestamp":"2019-02-05"}
},
{ "id":"3", 
  "metadata":{"version":"1.0","author":"user3","price":"10.0"}
}]

我正在尝试使用 jq 解析上述 json (data1.json),但我无法访问元数据对象。我最终将使用元数据对象作为字符串插入数据库。它可以有任意数量的字段,结构不固定。这是我正在使用的脚本。

#!/usr/bin/env bash
id=($(jq '.[] | .id' data1.json | tr -d '"'))
metadata=($(jq '.[] | .metadata' data1.json))

n_id=${#id[@]}
n_meta=${#metadata[@]}

echo $n_id 
echo $n_meta 

for (( i=0; i<n_id; i++ )); do
    echo ${metadata[$i]} 
done

预期输出:

{"version":"1.0","author":"user1"}

{"version":"1.0","author":"user2","timestamp":"2019-02-05"}

{"version":"1.0","author":"user3","price":"10.0"}

我在这里做错了什么?任何帮助表示赞赏。

【问题讨论】:

    标签: json bash parsing jq


    【解决方案1】:

    所有元数据对象,每行一个,未包装在数组中?

    $ jq -c '.[] | .metadata' data1.json
    {"version":"1.0","author":"user1"}
    {"version":"1.0","author":"user2","timestamp":"2019-02-05"}
    {"version":"1.0","author":"user3","price":"10.0"}
    

    但是您已经在您的 shell 代码中为您的 metadata 数组这样做了。如果你想每行打印一个数组:

    printf "%s\n" "${metadata[@]}"
    

    当对象内容中有空格时,将 jq 打印的行放入数组中:

    mapfile -t metadata < <(jq -c '.[] | .metadata' data1.json)
    

    while IFS= read -r obj; do metadata+=("$obj"); done < <(jq -c '.[] | .metadata' data1.json)
    

    【讨论】:

    • 非常感谢!这行得通!但我看到一个小问题,如果其中一个值中有空格,则对象不会按预期存储。例如,如果 "author":"fname lname" 在所有元数据对象中都有空格,它会在 fname 之后中断。
    • @prathyusha 添加了一些避免该问题的填充数组的方法。
    【解决方案2】:

    您可以使用jtc

    如果以上内容在文件foo.json中,可以这样做:

    % <foo.json jtc -tc -w '<metadata>l:'
    { "author": "user1", "version": "1.0" }
    { "author": "user2", "timestamp": "2019-02-05", "version": "1.0" }
    { "author": "user3", "price": "10.0", "version": "1.0" }
    

    -tc 表示“压缩输出格式”

    -w .. 是步行路径

    &lt;metadata&gt; 匹配“元数据”,l 表示标签匹配,: 表示“全部”

    【讨论】:

    • 最好使用-r 选项来确保步行的单行输出。因此完整的答案是:while IFS= read -r obj; do metadata+=("$obj"); done &lt; &lt;(jtc -w'&lt;metadata&gt;l:' -r data1.json)
    【解决方案3】:

    为什么不直接用 jq 过滤你的数据呢?

    jq -c '.[] | .metadata' data1.json
    

    请参考肖恩的回答,因为我没有考虑其他数据。

    【讨论】:

    • 我不知道元数据的内容,它可以是任何东西..所以我不能像你提到的那样设置字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2020-11-07
    相关资源
    最近更新 更多