Search code examples
jsonkeyjq

jq: pick and remove nested fields


Here is my json:

[
  {
    "id": "7250078e-5fbf-43d7-9c67-94b88fbf44d8",
    "priority": 0,
    "httpRequest": {
      "method": "POST",
      "path": "/catalog-data-rest/oid/search.xml",
      "headers": {
        "Host": [
          "preproduccio.gcatalegs.isisscat.intranet.gencat.cat:8443"
        ],
        "Authorization": [
          "Basic VVNVTVBJVFNUOkJ4c2w3MjU5"
        ],
        "User-Agent": [
          "curl/7.58.0"
        ],
        "Accept": [
          "*/*"
        ],
        "Content-Type": [
          "text/html; charset=utf-8"
        ],
        "Content-Length": [
          "94"
        ]
      },
      "keepAlive": true,
      "secure": true,
      "body": {
        "type": "STRING",
        "string": "<request><oid>2.16.724.4.402</oid><startIndex>1</startIndex><pageSize>100</pageSize></request>",
        "rawBytes": "PHJlcXVlc3Q+PG9pZD4yLjE2LjcyNC40LjQwMjwvb2lkPjxzdGFydEluZGV4PjE8L3N0YXJ0SW5kZXg+PHBhZ2VTaXplPjEwMDwvcGFnZVNpemU+PC9yZXF1ZXN0Pg==",
        "contentType": "text/html; charset=utf-8"
      }
    },
    "httpResponse": {
      "statusCode": 200,
      "reasonPhrase": "OK",
      "headers": {
        "Date": [
          "Tue, 20 Jul 2021 11:07:40 GMT"
        ],
        "X-Powered-By": [
          "Servlet/3.0"
        ],
        "X-Content-Type-Options": [
          "nosniff"
        ],
        "X-XSS-Protection": [
          "1; mode=block"
        ],
        "Cache-Control": [
          "no-cache, no-store, max-age=0, must-revalidate"
        ],
        "Pragma": [
          "no-cache"
        ],
        "Expires": [
          "0"
        ],
        "Strict-Transport-Security": [
          "max-age=31536000 ; includeSubDomains"
        ],
        "X-Frame-Options": [
          "DENY"
        ],
        "Set-Cookie": [
          "JSESSIONID=0000r6GgpYaB7bQiXRaS8zB8qw8:19pp48tgo; Path=/; HttpOnly"
        ],
        "Keep-Alive": [
          "timeout=10, max=100"
        ],
        "Connection": [
          "Keep-Alive"
        ],
        "Content-Type": [
          "application/xml"
        ],
        "Content-Language": [
          "en-US"
        ],
        "content-length": [
          "29089"
        ]
      },
      "cookies": {
        "JSESSIONID": "0000r6GgpYaB7bQiXRaS8zB8qw8:19pp48tgo"
      },
      "body": {
        "type": "XML",
        "xml": "string-value",
        "rawBytes": "string-value",
        "contentType": "application/xml"
      }
    },
    "times": {
      "remainingTimes": 1
    },
    "timeToLive": {
      "unlimited": true
    }
  }
]

I need to remove and pick following fields:

From .httpRequest I need to REMOVE:

.httpRequest.headers
.httpRequest.keepAlive
.httpRequest.secure
.httpRequest.body.rawBytes

Desired result:

    "httpRequest": {
      "method": "POST",
      "path": "/catalog-data-rest/oid/search.xml",
      "body": {
        "type": "STRING",
        "string": "<request><oid>2.16.724.4.402</oid><startIndex>1</startIndex><pageSize>100</pageSize></request>",
        "contentType": "text/html; charset=utf-8"
      }
    }

From .httpResponse I need to PICK:

.httpResponse.statusCode
.httpResponse.reasonPhrase
.httpResponse.headers.Content-Type
.httpResponse.headers.content-lenght

From .httpResponse I need to REMOVE:

.httpResponse.body.rawBytes

Desired result would be:

    "httpResponse": {
      "statusCode": 200,
      "reasonPhrase": "OK",
      "headers": {
        "Content-Type": [
          "application/xml"
        ],
        "content-length": [
          "29089"
        ]
      },
      "body": {
        "type": "XML",
        "xml": "string-value",
        "contentType": "application/xml"
      }
    }

So my final json would be:

[
  {
    "httpRequest": {
      "method": "POST",
      "path": "/catalog-data-rest/oid/search.xml",
      "body": {
        "type": "STRING",
        "string": "<request><oid>2.16.724.4.402</oid><startIndex>1</startIndex><pageSize>100</pageSize></request>",
        "contentType": "text/html; charset=utf-8"
      }
    },
    "httpResponse": {
      "statusCode": 200,
      "reasonPhrase": "OK",
      "headers": {
        "Content-Type": [
          "application/xml"
        ],
        "content-length": [
          "29089"
        ]
      },
      "body": {
        "type": "XML",
        "xml": "string-value",
        "contentType": "application/xml"
      }
    }
  }
]

I hope I've explained so well.

Up to now I've able to get this demo


Solution

  • Create a fresh object (using {}) when you want to pick, and use del when you want to remove.

    map({
       "httpRequest": (
          .httpRequest |
          del(.headers, .keepAlive, .secure, .body.rawBytes)
       ),
       "httpResponse": (
          .httpResponse |
          del(.body.rawBytes) |
          {
             statusCode,
             reasonPhrase,
             "headers": {
                "Content-Type":   .headers."Content-Type",
                "Content-Length": .headers."content-length"
             },
             body
          }
       )
    })
    

    jqplay

    The issue with both this solution and the previously-posted one is that HTTP headers are case-insensitive, so I don't think .headers."Content-Type" and .headers."content-length" will always work. Adjust as necessary.