Flatten / normalize json array of objects with jq Flatten / normalize json array of objects with jq json json

Flatten / normalize json array of objects with jq


Here is a simple script with hardcoded number of mirrors and primariness. Hope it will do the trick.

jq '    map(        { foreinKeyId } +        (            { primariness: 1, url },            (.urlMirror1 // empty | { primariness: 2, url: . }),            (.urlMirror2 // empty | { primariness: 3, url: . })        )    )' input.json


Here's a general solution, that is, it will handle arbitrarily many urlMirrors.

For the sake of clarity, let's begin by defining a helper function that emits a stream of {foreignKeyId, primariness, url} objects for a single input object:

def primarinesses:  {foreinKeyId} +    ({primariness:1, url},     (to_entries[]      | (.key | capture( "^urlMirror(?<n>[0-9]+)")) as $n      | {primariness: ($n.n | tonumber + 1), url : .value } )) ;

The solution is then simply:

[.[] | primarinesses]

which can also be written with less punctuation as:

map(primarinesses)


Given that OP has limited the query from generic down to a more specific criteria, the answer provided by @luciole75w is the best (most probably), refer to that one.

Now, for @oguzismail, this is a generic jtc approach (which will handle an arbitrary number of "urlMirror"s) made of 3 JSON transformation steps (updated solution):

<file.json jtc -w'<foreignKeyId>l:<f>v[-1]<urlM>L:<u>v[^0]' \               -i'{"url":{{u}},"foreignKeyId":{f}}' /\               -w'[foreignKeyId]:<f>q:<p:0>v[^0][foreignKeyId]:<f>s:[-1]<p>I1' \               -i'{"primeriness":{{p}}}' /\               -pw'<urlM>L:' -tc[   { "foreignKeyId": 1, "primeriness": 1, "url": "https://1-url.com" },   { "foreignKeyId": 2, "primeriness": 1, "url": "https://2-url.com" },   { "foreignKeyId": 3, "primeriness": 1, "url": "https://3-url.com" },   { "foreignKeyId": 2, "primeriness": 2, "url": "https://2-url-mirror-1.com" },   { "foreignKeyId": 3, "primeriness": 2, "url": "https://3-url-mirror-1.com" },   { "foreignKeyId": 3, "primeriness": 3, "url": "https://3-url-mirror-2.com" }]bash $ 

Explanation and visualization:

- all the 3 steps can be observed in a "slow-mo":
1. for each found "foreignKeyId" and each "urlMirror" found within the same record extend (insert into) the array with {"url":... , "foreignKeyId": ...}:

<file.json jtc -w'<foreignKeyId>l:<f>v[-1]<urlM>L:<u>v[^0]' \               -i'{"url":{{u}},"foreignKeyId":{f}}' -tc[   { "foreignKeyId": 1, "url": "https://1-url.com" },   { "foreignKeyId": 2, "url": "https://2-url.com", "urlMirror1": "https://2-url-mirror-1.com" },   { "foreignKeyId": 3, "url": "https://3-url.com", "urlMirror1": "https://3-url-mirror-1.com", "urlMirror2": "https://3-url-mirror-2.com" },   { "foreignKeyId": 2, "url": "https://2-url-mirror-1.com" },   { "foreignKeyId": 3, "url": "https://3-url-mirror-1.com" },   { "foreignKeyId": 3, "url": "https://3-url-mirror-2.com" }]bash $ 

2. now insert "primariness": N records based on the index of the occurrence of the foreignKeyId:

<file.json jtc -w'<foreignKeyId>l:<f>v[-1]<urlM>L:<u>v[^0]' \               -i'{"url":{{u}},"foreignKeyId":{f}}' /\               -w'[foreignKeyId]:<f>q:<p:0>v[^0][foreignKeyId]:<f>s:[-1]<p>I1' \               -i'{"primeriness":{{p}}}' -tc[   { "foreignKeyId": 1, "primeriness": 1, "url": "https://1-url.com" },   { "foreignKeyId": 2, "primeriness": 1, "url": "https://2-url.com", "urlMirror1": "https://2-url-mirror-1.com" },   { "foreignKeyId": 3, "primeriness": 1, "url": "https://3-url.com", "urlMirror1": "https://3-url-mirror-1.com", "urlMirror2": "https://3-url-mirror-2.com" },   { "foreignKeyId": 2, "primeriness": 2, "url": "https://2-url-mirror-1.com" },   { "foreignKeyId": 3, "primeriness": 2, "url": "https://3-url-mirror-1.com" },   { "foreignKeyId": 3, "primeriness": 3, "url": "https://3-url-mirror-2.com" }]bash $ 

3. and final step (-pw'<urlM>L:') - rid of all redundant "urlMirror"s records.

Optionally: if there's a requirement to sort all the records within the top array as per the OP's example, then this additional step will do: -jw'[foreignKeyId]:<>g:[-1]'

PS. it so happens that I'm also a developer of the jtc unix tool