简体   繁体   中英

how to denormalise this json structure

I have a json formatted overview of backups, generated using pgbackrest. For simplicity I removed a lot of clutter so the main structures remain. The list can contain multiple backup structures, I reduced here to just 1 for simplicity.

[
  {
    "backup": [
      {
        "archive": {
          "start": "000000090000000200000075",
          "stop": "000000090000000200000075"
        },
        "info": {
          "size": 1200934840
        },
        "label": "20220103-122051F",
        "type": "full"
      },
      {
        "archive": {
          "start": "00000009000000020000007D",
          "stop": "00000009000000020000007D"
        },
        "info": {
          "size": 1168586300
        },
        "label": "20220103-153304F_20220104-081304I",
        "type": "incr"
      }
    ],
    "name": "dbname1"
  }
]

Using jq I tried to generate a simpeler format out of this, until now without any luck.

What I would like to see is the backup.archive, backup.info, backup.label, backup.type, name combined in one simple structure, without getting into a cartesian product. I would be very happy to get the following output:

[
  {
    "backup": [
      {
        "archive": {
          "start": "000000090000000200000075",
          "stop": "000000090000000200000075"
        },
        "name": "dbname1",
        "info": {
          "size": 1200934840
        },
        "label": "20220103-122051F",
        "type": "full"
      },
      {
        "archive": {
          "start": "00000009000000020000007D",
          "stop": "00000009000000020000007D"
        },
        "name": "dbname1",
        "info": {
          "size": 1168586300
        },
        "label": "20220103-153304F_20220104-081304I",
        "type": "incr"
      }
    ]
  }
]

where name is redundantly added to the list. How can I use jq to convert the shown input to the requested output? In the end I just want to generate a simple csv from the data. Even with the simplified structure using

'.[].backup[].name + ":" + .[].backup[].type'

I get a cartesian product:

"dbname1:full"
"dbname1:full"
"dbname1:incr"
"dbname1:incr"

how to solve that?

So, for each object in the top-level array you want to pull in .name into each of its .backup array's elements, right? Then try

jq 'map(.backup[] += {name} | del(.name))'

Demo

Then, generating a CSV output using jq is easy: There is a builtin called @csv which transforms an array into a string of its values with quotes (if they are stringy) and separated by commas. So, all you need to do is to iteratively compose your desired values into arrays. At this point, removing .name is not necessary anymore as we are piecing together the array for CSV output anyway. And we're giving the -r flag to jq in order to make the output raw text rather than JSON.

jq -r '.[]
  | .backup[] + {name}
  | [(.archive | .start, .stop), .name, .info.size, .label, .type]
  | @csv
'

Demo

First navigate to backup and only then “print” the stuff you're interested.

.[].backup[] | .name + ":" + .type

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM