shell 如何动态更新一个json对象并将其放回原来的json对象?

ruarlubt  于 2023-02-05  发布在  Shell
关注(0)|答案(2)|浏览(197)

如何动态更新一个JSON对象并将其放回原始的JSON对象变量中?
我有一个包含以下JSON数据的变量。

test='[
  {
    "Name": "James",
    "Mobile": 12345678,
    "Gender": "Male",
    "Boolean": true,
    "Pet": "cat"
  },
  {
    "Name": "John",
    "Mobile": 1234567875,
    "Gender": "Male",
    "Boolean": true,
    "Pet": "rat"
  },
  {
    "Name": "Jennifer",
    "Mobile": 1234567890,
    "Gender": "Female",
    "Boolean": true,
    "Pet": "Dog"
  },
  {
    "Name": "Julia",
    "Mobile": 1234567890,
    "Gender": "Female",
    "Boolean": true,
    "Pet": "Dog"
  },
  {
    "Name": "Jeff",
    "Mobile": 9871234567890,
    "Gender": "Male",
    "Boolean": true,
    "Pet": "Fish"
  },
  {
    "Name": "Jones",
    "Mobile": 79871234567890,
    "Gender": "Female",
    "Boolean": true,
    "Pet": "Parrot"
  }
]'

items=$(echo "$test" | jq -c -r '.[]')
for item in ${items[@]}; do
    uName=$(echo $item | jq -r '.Name')
    if [ "$uName" == "John" ]; then
        echo "$item"
        echo " "
        modifiedTest=$(echo "$item" | jq  '.Name = "Tom"')
        modifiedTest=$(echo "$modifiedTest" | jq  '.Pet = "rabbit"')
        echo "$modifiedTest"
    fi    
done

现在,假设我们从上面的JSON对象中得到下面的第二个JSON对象

{
  "Name": "John",
  "Mobile": 1234567875,
  "Gender": "Male",
  "Boolean": true,
  "Pet": "rat"
}

我们用下面的代码更新了上面选择的JSON对象字段

{
  "Name": "Tom",
  "Mobile": 1234567875,
  "Gender": "Male",
  "Boolean": true,
  "Pet": "rabbit"
}

现在,我们如何将上述修改的JSON对象添加/更新回原始对象列表变量'test'的确切位置(本例中为第二个位置),但使用'Name=John'的过滤器,并以动态方式使用bash脚本,我们不知道此对象的确切索引位置?

iq0todco

iq0todco1#

工具jq可用于JSON操作:

jq '.[1].Name = "Tom" | .[1].Pet = "rabbit"' data.json

这将在控制台上输出修改后的文件。
请注意,一般来说jq [filter] data.json > data.json是不起作用的,即使看起来可以,也应该避免用这种方式覆盖输入文件。一种选择是使用shell变量:

json_data=$(jq '.[1].Name = "Tom" | .[1].Pet = "rabbit"' data.json)
echo $json_data > data.json

另一个选择是使用临时文件;还有一种方法是使用诸如X1 E0 F1 X中X1 M2 N1 X的实用程序。
请注意,您显示的文件不是有效的JSON,因此jq无法将其读取为JSON。为了解决这个问题,我将所有内容都用[]括起来,并删除了John对象中多余的逗号。

mlnl4t2r

mlnl4t2r2#

如果我们不知道该对象的确切索引位置,并使用“Name=John”过滤器,该怎么办?

< data.json jq '
  (map(.Name)| index("John")) as $ix 
  | (select($ix)
     | .[$ix] |= (.Name = "Tom" | .Pet = "rabbit")) // .
' | sponge data.json

但是您可能需要先备份data.json。

相关问题