Query JSON with Jq | Lakshmanshankar
Back to Blog
5 min read

Why do we need a JSON Query Parser

We developers deal with JSON objects everyday no matter what side of the application you are working on. And the ability to quickly query a complex json structure is a valuable skill to have jq is a tool that helps you to do exactly that.

What is Jq

jq is a lightweight command-line JSON processor. It’s expression language is designed for transforming JSON data through a pipeline of filters. Each filter takes an input and produces an output. Key Properties

jq-filter-functions

  • Immutable: Input JSON is never modified; all operations produce new values
  • Functional: Based on composable functions and filters
  • Stream-based: Each filter processes takes the input stream and produces an output stream which then can be piped just like how unix pipes.
  • Zero-Based: Array indexing starts at 0

Basics Usage of Jq

jq-blog on master [?] 
 jq 'keys' ./main.json             
[
  "appState",
  "elements",
  "files",
  "source",
  "type",
  "version"
]

jq-blog on master [?] 
 jq '.type' ./main.json                                                                                 
"excalidraw"

jq-blog on master [?] 
 jq '.version' ./main.json
2

We start with the basic one to list all the keys of json use key

jq 'keys' ./.json

keys will retrieve the list of keys of the json file, to filter only one specific key you can use .{key_name}. Jq syntax is flexible and immutable as each function returns a object that can be manipulated in upcoming function Example

Arrays

[
  {
    "one": 1
  },
  {
    "two": 2
  },
  {
    "three": 3
  },
  {
    "four": 4
  },
  {
    "five": 5
  },
  {
    "six": 6
  },
  {
    "seven": 7
  }
]

finding

commandexampleoutput
firstjq 'first{ one: 1}
lastjq 'last'{ seven: 7 }
nthjq 'nth(4){ five: 5 }
sub-arrayjq .[1:2][{ one: 1}]
by Indexjq .[3]{ “four”: 4}

Array Transformations

Jq transformations are very useful when you want to manipulate arrays.

echo '[1, 2, 2, 3]' | jq '[.[] | . * 2] | unique'
# Output: [2, 4, 6]

Here is a Typescript equivalent of jq code

const a = [1, 2, 3, 4, 5, 2];
const b = [...a].map((e) => e * 2); // [.[] | . *2]
const c = b.reduce((values: number[], acc) => { // | unique
  if (!values.includes(acc)) {
    values.push(acc);
  }
  return values;
}, []);
  • Maps each array element (.[] | . * 2).
  • Collects results into an array ([...]).
  • Filters unique values (unique).

Objects

.obj_key | [ .[] | . ] | first 

The above jq query will iterate a json object and convert it into a array and return its first item in it. Like javascript you can get only the keys of the specific object by using the keys query similiarly values will return the values only which also can be converted into an array for later transformations.

.block | values | map(.) | first

if you just want to list all the keys for the particular key in that object you can use the keys

.block | keys | first

Transforming objects

{
  "elements": [
    {
      "type": "line",
      "version": 1590,
      "versionNonce": 1831758985,
      "isDeleted": false,
      "id": "eJgo4I1DZ-w3jvmtemDpn"
    },
    {
      "type": "circle",
      "version": 1590,
      "versionNonce": 1831758985,
      "isDeleted": true,
      "id": "eJgo4I1DZ-x3jvdmemDpn"
    },
    {
      "type": "square",
      "version": 1590,
      "versionNonce": 1831758985,
      "isDeleted": true,
      "id": "eJgo4I1DZ-w3jvmtdslkpn"
    }
  ]
}

Jq command comes with a powerful set of filter which which helps you to filter only the neccessary information and you can combine filters with pipes then you can transform these objects. Eg is a below jq query that filters only the items that have isDeleted property set to true, and you can make these into a array of objects which is passed to next filter. if you wish you can transform the item in that.

.elements | [ .[] | select(.isDeleted == true) ] 

This jq will iterate the filtered array and create a new object(immutable) with the previously filtered result.

.elements | [ .[] | select(.isDeleted == true) ] | .[] | { id: .id, type: .type }

Bonus tips

If you are using jq then you might want to use jnv which is a rust wrapper for jq which helps you to run jq command interactively. No Need to start from scratch again and again. Check it out.

jnv-example-screen-shot

If you are using warp and using a same jq query in multiple places then you might want to use warp-workflow. which is a easiest way to changer particular argument without typing the whole command again and again.

warp-workflow-example-screen-shot

Lakshmanshankar © 2025