Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq command with several tables in the json path

Tags:

jq

My (huge) input file has many entries , what I want to extract is structured like that:

{
   "vulnerabilities": [
      {
         "parentAlert": {
            "affectedVersions": [
               {
                  "answers": [
                     {
                        "willBeFixed": true,
                        "fixedInPackage": "2.31.0"
                     }
                  ],
                  "productName": "LDEwS"
               },
               {
                  "answers": [
                     {
                        "willBeFixed": true,
                        "fixedInPackage": "2.32.0"
                     },
                     {
                        "willBeFixed": false,
                        "fixedInPackage": "3.0.0"
                     }
                  ],
                  "productName": "Foo"
               }
            ]
         }
      }
  ]
}

I want to extract the info of that type:

{
  "willBeFixed": true,
  "fixedInPackage": "2.31.0",
  "productName": "LDEwS"
}
{
  "willBeFixed": true,
  "fixedInPackage": "2.32.0",
  "productName": "Foo"
}
{
  "willBeFixed": false,
  "fixedInPackage": "3.0.0",
  "productName": "Foo"
}

I can't find the proper jp command. Can you please help to find out ?

The following command seems to work fine (for one field):

.vulnerabilities[] |
{
   willBeFixed: .parentAlert.affectedVersions[].answers[].willBeFixed
}
{
  "willBeFixed": true
}
{
  "willBeFixed": true
}
{
  "willBeFixed": false
}

But not the following ones.

.vulnerabilities[] |
{
   willBeFixed:    .parentAlert.affectedVersions[].answers[].willBeFixed,
   fixedInPackage: .parentAlert.affectedVersions[].answers[].fixedInPackage
}
.vulnerabilities[] |
{
   willBeFixed:    .parentAlert.affectedVersions[].answers[].willBeFixed,
   fixedInPackage: .parentAlert.affectedVersions[].answers[].fixedInPackage,
   productName:    .parentAlert.affectedVersions[].productName
}

It gives all possible combinations between the 2 fields in the first one and between the 3 fields in the second one.

{
  "willBeFixed": true,
  "fixedInPackage": "2.31.0"
}
{
  "willBeFixed": true,
  "fixedInPackage": "2.32.0"
}
{
  "willBeFixed": true,
  "fixedInPackage": "3.0.0"
}
{
  "willBeFixed": true,
  "fixedInPackage": "2.31.0"
}
...
like image 755
fabbb Avatar asked Dec 22 '25 22:12

fabbb


1 Answers

.parentAlert.affectedVersions[].answers[].willBeFixed will get all the willBeFixed values.

.parentAlert.affectedVersions[].answers[].fixedInPackage will independently get all the fixedInPackage values.

.parentAlert.affectedVersions[].productName will independently get all the productName values.

As you say, a crossproduct of the three lists will be used to merge them.

The problem is that these values are fetched independently. Instead, you need to "factor out" the independent loops into one loop.

.vulnerabilities[] |                           // For each vulnerability,
.parentAlert.affectedVersions[] |              //    For each affected version,
.productName as $productName |                 //       Save the product name.
.answers[] |                                   //          For each answer,
{ willBeFixed, fixedInPackage, $productName }  //             Build a dictionary.

Same thing:

.vulnerabilities[].parentAlert.affectedVersions[] |
.productName as $productName |
.answers[] |
{ willBeFixed, fixedInPackage, $productName }

Demo on jq playground

Alternative (from @pmf):

.vulnerabilities[].parentAlert.affectedVersions[] |
( .answers[] | { willBeFixed, fixedInPackage } ) + { productName }

Demo on jq playground

like image 65
ikegami Avatar answered Dec 31 '25 11:12

ikegami



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!