Home > Enterprise >  JQ: Filter json array as per stedolan JQ library
JQ: Filter json array as per stedolan JQ library

Time:07-20

I am quite new with JQ library. This is the incoming response:

{"message":"Details fetched successfully","status":1,"details":[{"test":"a","amount":2500.0,"pre":["11","429393","543216","987657"]},{"test":"b","amount":1500.0,"pre":["480855"]},{"test":"c","amount":0.0,"pre":["No data present"]},{"test":"d","amount":1500.0,"pre":["526702"]},{"test":"e","amount":2500.0,"pre":["No data present"]}]}

Output required after applying JQ filter:

  {
  "msg": "Details fetched successfully",
  "status": 1,
  "details": {
      "a": {
        "amount": 2500,
        "pre": [
          "11",
          "429393",
          "543216",
          "987657"
        ]
      },
      "b": {
        "amount": 1500,
        "pre": [
          "480855"
        ]
      },
      "c": {
        "amount": 0,
        "pre": [
          "No data present"
        ]
      },
      "d": {
        "amount": 1500,
        "pre": [
          "526702"
        ]
      },
      "e": {
        "amount": 2500,
        "pre": [
          "No data present"
        ]
      }
  }
}

I tried using the below JQ filter but I am getting "details" as array but "details" is object in final output.

JQ filter:

{msg: .message, status: .status, details: [.details[]| { (.test) : {amount: .amount, pre: .pre }}]}

CodePudding user response:

INDEX can turn an array into an object with keys based on a sub-expression:

jq '.details |= INDEX(.test)' 
{
  "message": "Details fetched successfully",
  "status": 1,
  "details": {
    "a": {
      "test": "a",
      "amount": 2500,
      "pre": [
        "11",
        "429393",
        "543216",
        "987657"
      ]
    },
    "b": {
      "test": "b",
      "amount": 1500,
      "pre": [
        "480855"
      ]
    },
    "c": {
      "test": "c",
      "amount": 0,
      "pre": [
        "No data present"
      ]
    },
    "d": {
      "test": "d",
      "amount": 1500,
      "pre": [
        "526702"
      ]
    },
    "e": {
      "test": "e",
      "amount": 2500,
      "pre": [
        "No data present"
      ]
    }
  }
}

Demo


To delete the test field from the result, use map_values with del on the resulting object:

jq '.details |= (INDEX(.test) | map_values(del(.test)))'
{
  "message": "Details fetched successfully",
  "status": 1,
  "details": {
    "a": {
      "amount": 2500,
      "pre": [
        "11",
        "429393",
        "543216",
        "987657"
      ]
    },
    "b": {
      "amount": 1500,
      "pre": [
        "480855"
      ]
    },
    "c": {
      "amount": 0,
      "pre": [
        "No data present"
      ]
    },
    "d": {
      "amount": 1500,
      "pre": [
        "526702"
      ]
    },
    "e": {
      "amount": 2500,
      "pre": [
        "No data present"
      ]
    }
  }
}

Demo

  • Related