i `jq`, a lightweight JSON parser · Dark Matter Industries

`jq`, a lightweight JSON parser

jq is a lightweight JSON parser. Unfortunately the usage is quite esoteric and anything written about it makes it more confusing. In this post I tackle one of the functions of jq: accessing values inside JSON objects.

You can either pipe stdout into jq or use jq with the following syntax:

$ jq -<flags> 'commands' <file>

Let’s say you have the following JSON string in a file called json-file:

{"one":"first field", "two":"second field", "three":{"three_one":"3 1", "three_two":"3 2"}, "four":[{"four_one":"4 1", "four_one_b":"4 1 b"}, {"four_two":"4 2"}]}

You can make it human readable with . (dot). The . is like the root level / in the shell:

$ jq '.' json-file
{
  "one": "first field",
  "two": "second field",
  "three": {
    "three_one": "3 1",
    "three_two": "3 2"
  },
  "four": [
    {
      "four_one": "4 1",
      "four_one_b": "4 1 b"
    },
    {
      "four_two": "4 2"
    }
  ]
}

# Note that if you pipe into `jq` you don't even need the dot
$ echo json-file | jq

Accessing the key:value pairs in the objects

Notice in this case we have a nested object in “three” and an array under “four” with 2 objects in that array.

So now to access the values of the top level:

$ jq '.["one"]' json-file
"first field"

$ jq '.["one", "two"]' json-file
"first field"
"second field"

$ jq '.["three"]' json-file
{
  "three_one": "3 1",
  "three_two": "3 2"
}

# Note the array denoted by the square brackets
$ jq '.["four"]' json
[
  {
    "four_one": "4 1",
    "four_one_b": "4 1 b"
  },
  {
    "four_two": "4 2"
  }
]

# To iterate through all the fields at the first level:
$ jq '.[]' json-file
"first field"
"second field"
{
  "three_one": "3 1",
  "three_two": "3 2"
}
[
  {
    "four_one": "4 1",
    "four_one_b": "4 1 b"
  },
  {
    "four_two": "4 2"
  }
]

In fact, you don’t need to use the indexing syntax and can use an object syntax:

$ jq '.one' json-file
"first field"

jq '.one, .two' json-file
"first field"
"second field"

How do we access the values inside “three”?

$  jq '.three.three_one, .three.three_two' json-file
"3 1"
"3 2"

# to iterate through all the values at this level
$ jq '.three[]' json-file
"3 1"
"3 2"

Now what about the array at “four”?

# List the level under "four", note the array `[`, `]`
$ jq '.four' json-file
[
  {
    "four_one": "4 1",
    "four_one_b": "4 1 b"
  },
  {
    "four_two": "4 2"
  }
]

# To iterate through all the elements inside the array:
% jq '.four[]' json-file
{
  "four_one": "4 1",
  "four_one_b": "4 1 b"
}
{
  "four_two": "4 2"
}
# Note that there are 2 objects inside this level.

# To access the elements inside the object, you have to use 
# An array index (which is a zero index)
$ jq '.four[0]' json-file
{
  "four_one": "4 1",
  "four_one_b": "4 1 b"
}

# And
$ jq '.four[1]' json-file
{
  "four_two": "4 2"
}

# This then gives us access to the objects at this level
$ jq '.four[0].four_one, .four[0].four_one_b' json
"4 1"
"4 1 b"

# To iterate through the object inside four[0]
$ jq '.four[0][]' json-file
"4 1"
"4 1 b"

We have only touched on how to access values inside nested objects and arrays in a JSON object using jq. jq has far more capabilities, including manipulating values inside the objects. More at a later date!