Сериализация и десериализация ассоциативного массива в bash с использованием jq - PullRequest
0 голосов
/ 22 января 2019

У меня есть некоторый код bash, который сериализует и десериализует одномерный ассоциативный массив в bash, используя jq.Он делает то, что я хочу сейчас, но у меня есть две проблемы.

Первая проблема заключается в том, что этот код кажется действительно неуклюжим.Особенно часть сериализации.Есть лучший способ сделать это?Либо с помощью jq, либо каким-либо другим способом?

Вторая проблема: я могу десериализовать вложенные данные (.eg, с {"data":{...}}), но я не могу понять, как обернуть вывод в ту же вложенную структуру,Как я могу воссоздать исходную структуру?

Редактировать: Уточнение.То, что я хочу сделать, это, с прокомментированным json, json='{"data": {"one": "1", "two": "2", "three": "3"}}' в коде примера и получить окончательный результат json='{"data": {"four": "4", "one": "100", "two": "2"}}.

Я могу прочитать в структуре 'data' и назначитьключ / значения правильно, но мне не везет в выяснении, как встроить конструкцию {"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 голосов
/ 22 января 2019

Это было бы менее клунко и, возможно, немного более надежно, если бы вместо:

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

у вас было:

jq -r 'to_entries[] | "\(.key)=\(.value)"'

И аналогично вы могли бы заменить forЦикл, используемый для создания объекта JSON с чем-то вроде:

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.

...