How to use JQ to expand a list of objects into denormalized objects?

I have the following example JSON strings:

{"toplevel_key": "top value 1", "list": [{"key1": "value 1", "key2": "value 2"},{"key1": "value 3", "key2": "value 4"}]}
{"toplevel_key": "top value 2", "list": [{"key1": "value 5", "key2": "value 6"}]}

I want to convert it using JQ, expanding the list to a fixed number of "columns", resulting in a list of flat JSON objects with the following format:

{
    "top-level-key": "top value 1",
    "list_0_key1": "value 1",
    "list_0_key2": "value 2",
    "list_1_key1": "value 3",
    "list_1_key2": "value 4",
}
{
    "top-level-key": "top value 2",
    "list_0_key1": "value 4",
    "list_0_key2": "value 5",
    "list_1_key1": "",
    "list_1_key2": "",
}

Note. I really want them one at a time, formatted here for readability.

The only way I was able to get the output I want is to write all the columns in my JQ expression:

$ cat example.jsonl | jq -c '{toplevel_key, list_0_key1: .list[0].key1, list_0_key2: .list[0].key2, list_1_key1: .list[1].key1, list_1_key2: .list[1].key2}'

This gives me the result that I want, but I have to manually write ALL fixed "columns" (and in the production process this will be much more).

, script JQ-, - , , JQ.

JQ?

, :

$ cat example.jsonl | jq -c '(.list | to_entries | map({("list_" + (.key | tostring)): .value})) | add'
{"list_0":{"key1":"value 1","key2":"value 2"},"list_1":{"key1":"value 3","key2":"value 4"}}
{"list_0":{"key1":"value 5","key2":"value 6"}}
+4
2

, . , , :

[leaf_paths as $path | {
    "key": $path | map(tostring) | join("_"),
    "value": getpath($path)
}] | from_entries

: paths - , , , , : - , . leaf_paths - , "", , .

, [[1, 2]], paths [0], [0, 0], [0, 1] ( [1, 2], 1 2 ), leaf_paths [0, 0], [0, 1].

. $path ( ["list", 1, "key2"]) map(tostring) ( ["list", "1", "key2"]) join . "" , : $path.

, from_entries, - JSON. , : , .

, , , . jq-, : , (-s) , :

(map(leaf_paths) | unique) as $paths |
map([$paths[] as $path | {
    "key": $path | map(tostring) | join("_"),
    "value": (getpath($path) // "")
}] | from_entries)[]

, : , slurped object $paths, , . (//) .

, !

+8

:

{ "top-level-key": .toplevel_key } + ([
    range(.list|length) as $i
        | .list[$i]
        | to_entries[]
        | .key = "list_\($i)_\(.key)"
    ] | from_entries)

.

{
  "top-level-key": "top value 1",
  "list_0_key1": "value 1",
  "list_0_key2": "value 2",
  "list_1_key1": "value 3",
  "list_1_key2": "value 4"
}
{
  "top-level-key": "top value 2",
  "list_0_key1": "value 5",
  "list_0_key2": "value 6"
}

, , , , . .

+4

Source: https://habr.com/ru/post/1612803/


All Articles