Home > other >  How to make jq to pick name value pairs
How to make jq to pick name value pairs

Time:06-05

Might be more or less the same ask as How to get JQ name/value pair from nested (array?) response?, but that question and example there is way too convoluted than what I'm asking --

Giving the input jason as in https://jqplay.org/s/jyKBnpx9NYX
Pick out all the name/value pair under .QueryString, .Params into the same unnested array

E.g., for an input of

{
    "Some": "Random stuff",
    "One": {
        "QueryString": [
           { "Name": "IsOrdered",    "Value": "1"              },
           { "Name": "TimeStamp",    "Value": "11654116426247" }
        ]
    },
    "Two": {
        "QueryString": [
           { "Name": "IsOrdered",    "Value": "1"              },
           { "Name": "TimeStamp",    "Value": "11654116426247" }
        ]
    },
    "Params": [
       { "Name": "ClassName",    "Value": "PRODUCT"        },
       { "Name": "ListID",       "Value": "Products"       },
       { "Name": "Mode ",        "Value": "1"              },
       { "Name": "Dept"  ,       "Value": "5"              },
       { "Name": "HasPrevOrder", "Value": ""               }
    ],
    "And": {
        "QueryString":[]
    },
    "More": "like",
    "More ": "this"
}

The output would be:

  [
    {
      "Name": "IsOrdered",
      "Value": "1"
    },
    {
      "Name": "TimeStamp",
      "Value": "11654116426247"
    },
    {
      "Name": "IsOrdered",
      "Value": "1"
    },
    {
      "Name": "TimeStamp",
      "Value": "11654116426247"
    },
    {
      "Name": "ClassName",
      "Value": "PRODUCT"
    },
    {
      "Name": "ListID",
      "Value": "Products"
    },
  ...
  ],

without any empty arrays output ([]), while keep the repeated values in the array.

I tried to remove empty arrays output ([]) by changing the jq expression from

[( .. | objects | ( .QueryString, .Params ) | select( . != null) )]

to

[( .. | objects | ( .QueryString, .Params ) | select( . != null && . != []) )]

but it failed.

And the final output need to be unnested into a single array too.

Bonus Q: Would it be possible to output each name/value pair on one line of their own like the following?

       { "Name": "IsOrdered",    "Value": "1"              },
       { "Name": "TimeStamp",    "Value": "11654116426247" },
       { "Name": "IsOrdered",    "Value": "1"              },
       { "Name": "TimeStamp",    "Value": "11654116426247" },

CodePudding user response:

The && must be replaced with and. On the result you can use | flatten to convert "array of arrays of objects" into just "array of objects".

Bonus A: Use the -c/--compact-output flag of jq together with | flatten[] instead of just | flatten.

Together:

jq -c '
[
    ..
    | objects
    | ( .QueryString, .Params )
    | select(. != null and . != [])
]
| flatten[]' input.json

Although this expression can be simplified into .. | objects | .QueryString[]?, .Params[]? The output is:

{"Name":"ClassName","Value":"PRODUCT"}
{"Name":"ListID","Value":"Products"}
{"Name":"Mode ","Value":"1"}
{"Name":"Dept","Value":"5"}
{"Name":"HasPrevOrder","Value":""}
{"Name":"IsOrdered","Value":"1"}
{"Name":"TimeStamp","Value":"11654116426247"}
{"Name":"IsOrdered","Value":"1"}
{"Name":"TimeStamp","Value":"11654116426247"}

CodePudding user response:

To get the Name/Value objects, one per line, you could go with:

jq -c '.. | objects | select( .Name and .Value)'
  • Related