Home > Net >  jq to change one thing and filter another
jq to change one thing and filter another

Time:06-06

Following on How to make jq to pick name value pairs, which will change/transform the name value pairs. Would it be possible to filter on another field in the same go, or I have to pipe the result to another jq to do the extra filtering?

Here is the test data: https://jqplay.org/s/_HqPFze-PhZ

The change/transform of the name value pairs under .QueryString, .Params has already been done. Now I want to further filter the result on the Headers record, and would only need the fields of Accept, User-Agent, and Referer, and discard any other fields that might exist. I.e.,

The final result would be the same as https://jqplay.org/s/_HqPFze-PhZ except that the the Headers record now only has the Accept, User-Agent, and Referer remains:

. . .
    "Headers": [
      {
        "Name": "Accept",
        "Value": "text/html, application/xhtml xml"
      },
      {
        "Name": "User-Agent",
        "Value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"
      },
      {
        "Name": "Referer",
        "Value": "http://mytest.com/sign_in"
      }
    ]
. . .

Everything else should remain the same as the sample output.

CodePudding user response:

You can chain as many assignments as necessary :

jq '( .. | objects | ( .QueryString, .Params ) | select(.) )
         |= ( map( @uri "\( .Name )=\( .Value )" ) | join("&") )
    |
    ( .. | objects | .Headers | select(.) )
         |= map(select(.Name|IN("Accept", "Referer", "User-Agent")))
   '

Using walk is more performant :

jq 'walk(
      ( objects | ( .QueryString, .Params ) | select(.) )
         |= ( map( @uri "\( .Name )=\( .Value )" ) | join("&") )
      |
      ( objects | .Headers | select(.) )
         |= map(select(.Name|IN("Accept", "Referer", "User-Agent")))
   )'
  • Related