在bash中使用jq序列化和反序列化关联数组

在bash中使用jq序列化和反序列化关联数组,bash,jq,Bash,Jq,我有一些bash代码,它使用jq对bash中的一维关联数组进行序列化和反序列化。这正是我现在想要的,但我有两个问题 第一个问题是,这段代码感觉非常糟糕。特别是序列化部分。有更好的方法吗?要么用jq,要么用其他方式 第二个问题是,我可以反序列化嵌套数据(.例如,使用{“data”:{…}}),但我不知道如何在相同的嵌套结构中包装输出。如何重建原始结构 编辑:澄清。我想要做的是,在示例代码中,使用注释的json,json='{“数据”:{“一”:“1”、“二”:“2”、“三”:“3”}',并得到最终

我有一些bash代码,它使用jq对bash中的一维关联数组进行序列化和反序列化。这正是我现在想要的,但我有两个问题

第一个问题是,这段代码感觉非常糟糕。特别是序列化部分。有更好的方法吗?要么用jq,要么用其他方式

第二个问题是,我可以反序列化嵌套数据(.例如,使用
{“data”:{…}}
),但我不知道如何在相同的嵌套结构中包装输出。如何重建原始结构

编辑:澄清。我想要做的是,在示例代码中,使用注释的json,
json='{“数据”:{“一”:“1”、“二”:“2”、“三”:“3”}'
,并得到最终结果

json='{“数据”:{“四”:“4”,“一”:“100”,“二”:“2”}
转储

我可以读入'data'结构并正确地分配键/值,但我不知道如何将
{“four”:…}
构造嵌入
“data”:{…}
对象

编辑2:我第二期的答案与peak的答案结合如下:

for key in "${!aaname[@]}"; do
  printf '%s\n%s\n' "$key" "${aaname[$key]}"
done | jq -SRn '.data = ([inputs | {(.): input}] | add)'
代码是:

#!/bin/bash

#json='{"data": {"one": "1", "two": "2", "three": "3"}}'
json='{"one": "1", "two": "2", "three": "3"}'

#------------------------------------------------------------------------------
# De-serialize data

declare -A aaname

while IFS='=' read -r key value; do
  aaname["$key"]="$value"
done < <(echo "$json" | jq -r '. | to_entries | .[] | .key + "=" + .value ')
#done < <(echo "$json" | jq -r '.data | to_entries | .[] | .key + "=" + .value ')

#------------------------------------------------------------------------------
# Manipulate data

# Change existing value ...
aaname['one']='100'

# Add element ...
aaname['four']='4'

# Remove element ...
unset aaname['three']

#------------------------------------------------------------------------------
# Serialize data

# Why can't I use ${#aaname[@]} in ((...))?
total="${#aaname[@]}"
count=0

{
  printf '['
  for key in "${!aaname[@]}"; do
    printf '{"key": "%s", "value": "%s"}' "$key" "${aaname[$key]}"
    ((++count < total)) && printf ','
  done
  printf ']'
#}
#} | jq -S ' . | "data{" + from_entries + "}"'
} | jq -S ' . | from_entries'

# gives
#
#{
#  "four": "4",
#  "one": "100",
#  "two": "2"
#}
#/bin/bash
#json='{“数据”:{“一”:“1”、“二”:“2”、“三”:“3”}'
json='{“一”:“1”,“二”:“2”,“三”:“3”}'
#------------------------------------------------------------------------------
#反序列化数据
声明-名称
而IFS='='读取-r键值;做
aa名称[“$key”]=“$value”

如果不是:

jq -r '. | to_entries | .[] | .key + "=" + .value ')
你有:

jq -r 'to_entries[] | "\(.key)=\(.value)"'
类似地,您可以将用于创建JSON对象的
for
循环替换为如下内容:

for key in "${!aaname[@]}"; do
    printf "%s\n" "$key"
    printf "%s\n" "${aaname[$key]}"
done | jq -Rn '[inputs | { (.): input}] | add'
关于第二个问题,恐怕你的问题我不太清楚。 您希望非JSON表示的格式是什么? 您期望的序列化/反序列化解决方案的通用性如何?
在这方面,您可能希望查看
jq--stream的输出。我认为您的代码不适用于问题中提供的嵌套JSON结构。注释代码在反序列化数据时工作,但在序列化时不工作。谢谢。这两段代码看起来显然不那么麻烦。为我的第二个问题添加了一个澄清。一个
printf
就足够了:
printf%s\\n“$key”“${aaname[$key]}”
。你甚至可以用
(${aaname[@]})替换循环&粘贴-d\\n我也注意到了这一点。然而,依赖于关联数组中的特定顺序——特别是当文档没有明确声明顺序得到维护时——我在过去最糟糕的时刻遇到了这种情况。另外,在这个特殊的例子中,这并不重要,因为我对jq使用了“-S”选项,因为它对键进行排序。