Zounadire
Zounadire

Reputation: 1574

How can I remove a nested key-value pair, whose value has a deeper nested array with a specific value by using jq

I am currently trying to filter out some path values from a swagger json document, by using jq.

The JSON looks something like this:

{
  "swagger": "2.0",
  "info": {
    "version": "1.0.2",
    "title": "Some API"
  },
  "host": "example.com",
  "basePath": "/",
  "paths": {
    "/api/companies": {
      "get": {
        "tags": [ "company-tag" ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": { "$ref": "#/definitions/CompanyDTO" }
          }
        }
      }
    },
    "/api/account": {
      "get": {
        "tags": [ "account-tag" ],
        "operationId": "getAccount",
        "responses": {
          "200": {
            "description": "OK",
            "schema": { "$ref": "#/definitions/UserDTO" }
          }
        }
      },
      "post": {
        "tags": [ "account-tag" ],
        "operationId": "createAccount",
        "responses": {
          "200": {
            "description": "OK",
            "schema": { "$ref": "#/definitions/UserDTO" }
          }
        }
      }
    }
  }
}

I would like to filter the paths values, so that I can get only the paths that contain a specific tag inside the tags array.

For example: if I want to get the paths for the account-tag the JSON should look like this after filtering:

{
  "swagger": "2.0",
  "info": {
    "version": "1.0.2",
    "title": "Some API"
  },
  "host": "example.com",
  "basePath": "/",
  "paths": {
    "/api/account": {
      "get": {
        "tags": [ "account-tag" ],
        "operationId": "getAccount",
        "responses": {
          "200": {
            "description": "OK",
            "schema": { "$ref": "#/definitions/UserDTO" }
          }
        }
      },
      "post": {
        "tags": [ "account-tag" ],
        "operationId": "createAccount",
        "responses": {
          "200": {
            "description": "OK",
            "schema": { "$ref": "#/definitions/UserDTO" }
          }
        }
      }
    }
  }
}

EDIT

Ikegami's second suggestion worked as expected. Here is my final solution

Upvotes: 0

Views: 124

Answers (1)

ikegami
ikegami

Reputation: 386406

If we assume all methods (get, post, etc) of a given path share the same tags, we can simply use the following:

.paths |= with_entries( select( .value[].tags | index("account-tag") ) )

Demo on jqplay


If that assumption doesn't hold, we'll need to filter at two levels.

.paths |= with_entries(
   .value |= with_entries(
      select( .value.tags | index("account-tag") )
   ) |
   select( .value | length > 0 )
)

Demo on jqplay

or

.paths |= with_entries(
   .value = (
      .value |
      with_entries(
         select( .value.tags | index("account-tag") )
      ) |
      select( length > 0 )
   )
)

Demo on jqplay

(I hate that I have to use .value = ( .value | ... ) instead of .value |= ( ... ) here.)

Upvotes: 1

Related Questions