使用jq将json对象动态添加到数组中

时间:2017-03-18 17:58:20

标签: json bash command-line jq

以下是我的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元素动态添加到departments数组的代码

#!/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对象动态添加到数组中?

由于

2 个答案:

答案 0 :(得分:2)

可以在不多次调用jq的情况下完成任务。

非常类似于以下内容就足够了:

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

此解决方案当然假定.json文件都包含有效的JSON。

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

答案 1 :(得分:1)

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

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