As a full-stack developer and Linux professional, I often need to parse, filter, and transform JSON data from APIs, config files, or other applications. JQ is an indispensable tool for working with JSON in Linux and Unix-like environments.

In this comprehensive guide, I will provide 15 practical examples of using JQ to process JSON data in the terminal. We will cover basic and advanced filters, arithmetic operations, sorting, grouping, mapping keys, and more. By the end, you will have a solid grasp of this useful command-line JSON processor.

Prerequisites

Before we dive into the examples, let‘s cover some prerequisites:

Install JQ

If you don‘t already have JQ installed, you can install it on most Linux distributions using your package manager:

sudo apt install jq # Debian/Ubuntu
sudo dnf install jq # Fedora 
sudo pacman -S jq # Arch Linux

Sample JSON Data

For demonstration purposes, we will use the following sample JSON document containing data on programming languages:

[
  {
    "name": "Python",
    "type": "interpreted",
    "year": 1991,
    "extensions": [
      ".py",
      ".pyw",
      ".pyc",
      ".pyd"  
    ]
  },
  {
    "name": "JavaScript",
    "type": "interpreted",
    "year": 1995,
    "extensions": [
      ".js",
      ".mjs",
      ".cjs"  
    ]
  },
  {
    "name": "Java",
    "type": "compiled",
    "year": 1995,
    "extensions": [
      ".java",
      ".class",
      ".jar"
    ]
  } 
]

We will save this JSON array to a file called languages.json to use in our examples.

1. Read JSON Data from a File

The most basic usage of JQ is to parse JSON data from a file. The following command will output the contents of languages.json in a formatted JSON tree:

jq ‘.‘ languages.json

Output:

[
  {
    "name": "Python",
    "type": "interpreted",
    "year": 1991,
    "extensions": [
      ".py",
      ".pyw",
      ".pyc",
      ".pyd"
    ]
  },
  {
    "name": "JavaScript",
    "type": "interpreted",
    "year": 1995,
    "extensions": [
      ".js",
      ".mjs",
      ".cjs"
    ]
  },
  {
    "name": "Java",
    "type": "compiled",
    "year": 1995,
    "extensions": [
      ".java",
      ".class",
      ".jar"
    ]
  }
]

The . operator instructs JQ to output the JSON data unchanged.

2. Read JSON Data from stdin

We can also pipe JSON data directly into JQ from another command rather than specifying a file:

cat languages.json | jq ‘.‘

This allows us to reuse JQ filters on the fly for quick parsing.

3. Compact vs Pretty Print Output

By default JQ prints formatted, colorized output intended for human readability.

We can compact the output to a single line using the -c flag:

jq -c ‘.‘ languages.json

Output:

[{"name":"Python","type":"interpreted","year":1991,"extensions":[".py",".pyw",".pyc",".pyd"]},{"name":"JavaScript","type":"interpreted","year":1995,"extensions":[".js",".mjs",".cjs"]},{"name":"Java","type":"compiled","year":1995,"extensions":[".java",".class",".jar"]}]

Conversely, we can force pretty-printing with color output using -C even when redirecting to a file:

jq -C ‘.‘ languages.json > output.json

4. Filter JSON Data by Key

To output just the values for a specific key, we can use a filtering expression:

jq ‘.[].name‘ languages.json

Output:

"Python"
"JavaScript" 
"Java"

We can also return multiple keys using comma separation:

jq ‘.[].name, .[].year‘ languages.json

Output:

"Python"
1991
"JavaScript"
1995
"Java" 
1995

5. Filter JSON Data by Index

To retrieve a single object within a JSON array based on its index, we specify the index in brackets:

jq ‘.[1]‘ languages.json

Output:

{
  "name": "JavaScript",
  "type": "interpreted",
  "year": 1995,
  "extensions": [
    ".js",
    ".mjs",
    ".cjs"
  ]
}

This outputs just the second language, JavaScript, from our array.

6. Filter JSON Data by Nested Key

To access nested objects and arrays, we can chain operators:

jq ‘.[].extensions[1]‘ languages.json

Output:

".pyw"
".mjs"
".class"

Here we output the second extension defined for each language.

7. Use Conditionals to Filter JSON Data

We can also filter objects conditionally based on key values using select() and comparative operators:

jq ‘.[] | select(.year > 2000)‘ languages.json

Output:

{
  "name": "Python",
  "type": "interpreted",
  "year": 1991,
  "extensions": [
    ".py",
    ".pyw",
    ".pyc",
    ".pyd"
  ]
}

This filters for only language definitions where year is greater than 2000, returning just Python.

8. Sort Filtered JSON Data

To sort an array of JSON objects by key, we can pipe the filtered data into sort_by():

jq ‘.[] | select(.type=="interpreted") | sort_by(.name)‘ languages.json

Output:

{
  "name": "JavaScript",
  "type": "interpreted",
  "year": 1995,
  "extensions": [
    ".js",
    ".mjs", 
    ".cjs"
  ]
}
{
  "name": "Python",
  "type": "interpreted",
  "year": 1991,
  "extensions": [
    ".py",
    ".pyw",
    ".pyc",
    ".pyd"
  ]
}

Here we filter to just interpreted languages first, then sort them by name.

9. Group Filtered JSON Data by Key

To group arrays of JSON data based on similarities in key values, we can use group_by():

jq ‘.[] | group_by(.type)‘ languages.json

Output:

{
  "interpreted": [
    {
      "name": "Python",
      "type": "interpreted",
      "year": 1991,
      "extensions": [
        ".py",
        ".pyw",
        ".pyc",
        ".pyd"  
      ]
    },
    {
      "name": "JavaScript",
      "type": "interpreted",
      "year": 1995,
      "extensions": [
        ".js",
        ".mjs",
        ".cjs"
      ]
    }
  ],
  "compiled": [
    {
      "name": "Java",
      "type": "compiled",
      "year": 1995,
      "extensions": [
        ".java",
        ".class",
        ".jar"  
      ]
    }
  ]
}

We‘ve grouped languages by their type, showing the power of JQ for data analysis.

10. Use Arithmetic Operators

For basic arithmetic on JSON values, we can use operators like +, -, *, and /.

Let‘s sum the year values of our programming languages:

jq ‘.[0].year + .[1].year + .[2].year‘ languages.json

Output:

1991 + 1995 + 1995 = 5991

We can also find the average founding year:

(.[0].year + .[1].year + .[2].year) / length

Output:

1997

11. Map JSON Data to Custom Keys

To rename or remap JSON keys to more convenient values, JQ allows key/value pair mapping:

jq ‘{name: .[].name, released: .[].year}‘ languages.json

Output:

{
  "name": "Python",
  "released": 1991 
}
{  
  "name": "JavaScript",
  "released": 1995
}
{
  "name": "Java", 
  "released": 1995
}

Here we have mapped the name and year keys to more readable released keys.

12. Append Key/Value Pairs to JSON Objects

Building on the previous example, we may want to add some additional metadata to each language object. JQ makes this easy through the + operator:

jq ‘{name: .name, released: .year} + {popular: true}‘ languages.json

Output:

{
  "name": "Python",
  "released": 1991,
  "popular": true
}
{
  "name": "JavaScript",
  "released": 1995,
  "popular": true  
}
{
  "name": "Java",
  "released": 1995,
  "popular": true
}

We have appended a new boolean key popular to every language.

13. Modify JSON Array Values

JQ allows performing operations across all elements in a JSON array easily. For example, to increment the year of each language definition:

jq ‘.[] | .year += 1‘ languages.json

Output:

{
  "name": "Python",
  "type": "interpreted",
  "year": 1992,
  "extensions": [
    ".py",
    ".pyw", 
    ".pyc",
    ".pyd"
  ]
} 
{
  "name": "JavaScript",
  "type": "interpreted", 
  "year": 1996,
  "extensions": [
    ".js",
    ".mjs",
    ".cjs"  
  ]
}
{
  "name": "Java",
  "type": "compiled",
  "year": 1996,
  "extensions": [
    ".java",
    ".class",
    ".jar"
  ]
}

Here we incremented the founding year of each language using the += operator.

14. Limit JSON Data Size

When processing large JSON documents, it can be handy to limit output size using limit():

jq ‘.[] | limit(1;.[0])‘ languages.json 

Output:

  {
    "name": "Python"
  }
{
    "name": "JavaScript"
}
{
   "name": "Java"
}

Here we limited the output to only the first key/value pair of each object.

15. Omit Keys from JSON Objects

We can also explicitly omit keys from JSON output using del():

jq ‘del(.year)‘ languages.json

Output:

[
  {
    "name": "Python", 
    "type": "interpreted",
    "extensions": [
      ".py",
      ".pyw",
      ".pyc",
      ".pyd"  
    ]
  },
  {
    "name": "JavaScript",
    "type": "interpreted",  
    "extensions": [
      ".js",
      ".mjs",
      ".cjs"   
    ]
  },
  {
    "name": "Java",
    "type": "compiled",
    "extensions": [
      ".java",
      ".class",
      ".jar"
    ]
  }  
]

Here we removed the year keys completely, keeping the rest of the objects intact.

Summary

These examples demonstrate powerful manipulation of JSON data programmatically without manually editing files. JQ helps queries, transform, filter, map, and reduce JSON right from the terminal or shell scripts.

I encourage you to explore further and apply these techniques to your own JSON processing needs. The jq manual contains many more advanced examples for scenarios like working with streams, hashes, $ARGV, errors, JSON lines, and multiple inputs.

Let me know in the comments if have any other questions on practical jq usage! I‘m happy to provide any clarification or additional examples.

Similar Posts