【问题标题】:Dynamically add json object into array with jq使用 jq 将 json 对象动态添加到数组中
【发布时间】:2023-04-02 21:40:01
【问题描述】:

下面是我的employee.json文件的模板

{
    "orgConfig": {
        "departments": []
    }
}

部门将有如下的一系列部门

{
    "name" : "physics",
    "id" : "1234",
    "head" : "abcd"
}

类似

{
    "name" : "chemistry",
    "id" : "3421",
    "head" : "xyz"
}

所以我要构建的最终数组结构如下

{
    "orgConfig": {
        "departments": [
            {
                "name" : "physics",
                "id" : "1234",
                "head" : "abcd"
            },
            {
                "name" : "chemistry",
                "id" : "3421",
                "head" : "xyz"
            },
            {
                "name" : "Maths",
                "id" : "4634",
                "head" : "jklm"
            }
        ]
    }
}

下面是我将 json 元素动态添加到部门数组的代码

#!/bin/bash

source department.properties   # will have departments=physiscs,chemistry,Maths,computers .. etc
IFS=',' read -ra NAMES <<< "$departmentsToImport"

position=0
for i in "${NAMES[@]}"; do
    #./jsonfiles will chemistry.json, physics.json, Maths.json etc
    value=`cat ./jsonfiles/$i.json`    

    if [ $position -eq 0 ]
    then
       cat employee.json | jq --arg value "$value" '.orgConfig.departments[0] |= .+ $value' > tmp.json && mv tmp.json employee.json
    else
       cat employee.json | jq --arg position "$position" value "$value" '.orgConfig.departments[$position] |= .+ $value' > tmp.json && mv tmp.json employee.json
    fi
    ((position++))
    rm -rf tmp.json
done

exit $?

但程序抛出以下错误

jq: error (at <stdin>:51): Cannot index array with string "1"

但是如果使用直接索引而不是可变位置,那么它工作正常。

cat employee.json | jq --argjson value "$value" '.orgConfig.departments[1] |= .+ $value' > tmp.json && mv tmp.json employee.json 

我不知道我有多少部门的键值图。我无法对索引进行硬编码。对上述问题有什么帮助并动态地将 json 对象添加到数组中?

谢谢

【问题讨论】:

    标签: json bash command-line jq


    【解决方案1】:

    这可以通过关闭jq 的自动输入读取来完成,然后将第一个显式输入通过过滤器传递,该过滤器使用剩余的显式输入修改其输入。有道理?没有:) 但是代码本身很简单:

    jq -n 'input | .orgConfig.departments += [inputs]' \
      employee.json chemistry.json physics.json math.json
    
    1. 第一个 input 从第一个参数 (employee.json) 中读取。
    2. += 的输入来自input 过滤器。它的左操作数 选择要更新的字段;右操作数提供值 更新它。
    3. inputs 从剩余的命令行参数中读取,并将它们的内容放入一个数组中,每个文件都放在一个单独的元素中。

    将此与您的 shell 代码结合以选择正确的课程文件产生

    source department.properties
    IFS=, read -ra NAMES <<< "$departmentsToImport"
    for c in "${NAMES[@]}"; do
        courses+=("./jsonfiles/$c.json")
    done
    jq -n 'input | .orgConfig.departments += [inputs]' employee.json "${courses[@]}"
    

    【讨论】:

    • 感谢@chepner 的大力帮助。解决了我的问题。
    【解决方案2】:

    无需多次调用 jq 即可完成任务。

    以下内容就足够了:

    jq -s '{orgConfig: {departments: . }}' jsonfiles/*.json
    

    这个解决方案当然假设 .json 文件都包含有效的 JSON。

    诀窍是使用 -s(又名 --slurp)选项,因为这会将输入转换为您的数组。您可能会发现使用 -s 会比其他一些方法产生更好的运行时间。

    【讨论】:

    • 谢谢@peak,根据你上面给出的解决方案得到了新的要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 2018-07-20
    • 2013-02-27
    • 1970-01-01
    • 2021-03-16
    相关资源
    最近更新 更多