2

Some simple JSON arrives and looks like this. I need to convert it to shell variables, the keys should be uppercase, and also "-" should be converted "_", and finally all key names should be put in shell list to generate the output which you can see below. I managed to do this with a complicated pipe of jq queries, I am wondering if there is a more simple way to do this I jq? Note that the __INDEX0,__INDEX1,... variables in the final output would not be required.

JSON INPUT (input.json)

{
  "msg-version": "1.0",
  "msg-type":  "app-config",
  "content": "aaa"
}
{
  "msg-version": "1.0",
  "msg-type":  "app-config",
  "content": "bbb"
}
{
  "msg-version": "1.0",
  "msg-type":  "app-config",
  "content": "ddd",
  "breakit": { "a":"b"}
}

SHELL OUTPUT

__INDEX0='0'
MSG_VERSION0='1.0'
MSG_TYPE0='app-config'
CONTENT0='aaa'
__INDEX_NAMES0='CONTENT MSG_TYPE MSG_VERSION'
__INDEX1='1'
MSG_VERSION1='1.0'
MSG_TYPE1='app-config'
CONTENT1='bbb'
__INDEX_NAMES1='CONTENT MSG_TYPE MSG_VERSION'
__INDEX2='2'
MSG_VERSION2='1.0'
MSG_TYPE2='app-config'
CONTENT2='ddd'
BREAKIT2='{"a":"b"}'
__INDEX_NAMES2='BREAKIT CONTENT MSG_TYPE MSG_VERSION'

bash jq quer(ies)

cat input.json|\
jq  'keys as $keys|. + {"__index_names": ($keys|join(" ")|split("-")|join("_")|ascii_upcase)}'|\
jq --slurp 'keys[] as $_k|{ __index: $_k|tostring}*  .[$_k]  '|\
jq -r '.__index as $i|to_entries| .[]| { key: ((.key + $i)|split("-")|join("_")|ascii_upcase), value: (.value) }|.key + "='"'"'" + (.value|tostring) + "'"'"'"')
3
  • That input is not JSON! It can be treated like multiple JSON files pasted together, but that's an important difference. Commented Jun 2, 2021 at 20:50
  • @UlrickEckhardt - You're right but jq handles JSON streams without fuss. See en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON Commented Jun 2, 2021 at 22:04
  • @UlrichEckhardt changed the topic to reflect your comment Commented Jun 3, 2021 at 4:25

1 Answer 1

1

Using the jq command-line options -n and -r, the following produces the output as required (that is, without the superfluous __INDEX keys):

def q: if type=="string" then @sh else tojson|@sh end;

foreach inputs as $in (-1;.+1;
  . as $n
  | $in
  | to_entries[]
  | "\(.key|gsub("-";"_")|ascii_upcase + ($n|tostring) )=\(.value|q)"
  )

The tricky bit here, of course, is adding the integer suffixes to the key names.

Sign up to request clarification or add additional context in comments.

1 Comment

what a simple solution, thank you very much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.