2

I have a Redis hash with keys and values like string key -- serialized JSON value. Corresponding rediscli query (hgetall some_redis_hash) being dumped in a file:

redis_key1
{"value1__key1": "value1__value1", "value1__key2": "value1__value2" ...}
redis_key2
{"value2__key1": "value2__value1", "value2__key2": "value2__value2" ...}
...
and so on.

So the question is, how do I pretty-print these values enclosed in brackets? (note that key strings between are making the document invalid, if you'll try to parse the entire one) The first thought is to get particular pairs from Redis, strip parasite keys, and use jq on the remaining valid JSON, as shown below:

rediscli hget some_redis_hash redis_key1 > file && tail -n +2 file
- file now contains valid JSON as value, the first string representing Redis key is stripped by tail -
cat file | jq
- produces pretty-printed value -

So the question is, how to pretty-print without such preprocessing? Or (would be better in this particular case) how to merge keys and values in one big JSON, where Redis keys, accessible on the upper level, will be followed by dicts of their values? Like that:

rediscli hgetall some_redis_hash > file
cat file | cool_parser
- prints { "redis_key1": {"value1__key1": "value1__value1", ...}, "redis_key2": ... }

1 Answers1

2

A simple way for just pretty-printing would be the following:

cat file | jq --raw-input --raw-output '. as $raw | try fromjson catch $raw'

It tries to parse each line as json with fromjson, and just outputs the original line (with $raw) if it can't.

(The --raw-input is there so that we can invoke fromjson enclosed in a try instead of running it on every line directly, and --raw-output is there so that any non-json lines are not enclosed in quotes in the output.)


A solution for the second part of your questions using only jq:

cat file \
    | jq --raw-input --null-input '[inputs] | _nwise(2) | {(.[0]): .[1] | fromjson}' \
    | jq --null-input '[inputs] | add'
  • --null-input combined with [inputs] produces the whole input as an array
  • which _nwise(2) then chunks into groups of two (more info on _nwise)
  • which {(.[0]): .[1] | fromjson} then transforms into a list of jsons
  • which | jq --null-input '[inputs] | add' then combines into a single json

Or in a single jq invocation:

cat file | jq --raw-input --null-input \
    '[ [inputs] | _nwise(2) | {(.[0]): .[1] | fromjson} ] | add'

...but by that point you might be better off writing an easier to understand python script.

mihi
  • 3,097
  • 16
  • 26