使用jq

时间:2019-01-22 03:41:45

标签: bash jq

我有一些bash代码,可以使用jq对bash中的一维关联数组进行序列化和反序列化。它可以满足我目前的需求,但是有两个问题。

第一个问题是,这段代码实在太笨拙了。特别是序列化部分。有一个更好的方法吗?用jq还是其他方式?

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

编辑:澄清。我想做的是,在示例代码中加上注释的json,json='{"data": {"one": "1", "two": "2", "three": "3"}}',并丢弃 json='{"data": {"four": "4", "one": "100", "two": "2"}}的最终结果。

我可以读取“数据”结构并正确分配键/值,但是我对确定如何将{"four": ...}构造嵌入到"data": {...}对象中没有任何运气。

编辑2:结合第二个问题,我的第二个问题的答案如下:

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"
#}

1 个答案:

答案 0 :(得分:1)

如果不是这样的话,它会不太笨拙,也许会更健壮

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"的输出 各种JSON文本。