What it is
jq is a lightweight and flexible command-line JSON processor. You reach for it when you need to slice, filter, transform, and format JSON data from the command line.
Installation
Linux (Debian/Ubuntu):
sudo apt update
sudo apt install jq
Linux (Fedora):
sudo dnf install jq
macOS:
brew install jq
Windows: Download the executable from the jq releases page and place it in your system’s PATH. Alternatively, using Chocolatey:
choco install jq
Core Concepts
- Filters:
jqoperates on JSON data using filters. A filter is an expression that takes JSON as input and produces JSON as output. The simplest filter is., which represents the entire input JSON. - Identity (
.): The identity filter (.) outputs the input JSON unchanged. - Object Identifier (
.key): Selects the value associated with a specific key in an object. - Array Index (
.[index]): Selects an element from an array by its zero-based index. - Array Slicing (
.[start:end]): Extracts a sub-array.startis inclusive,endis exclusive. - Piping (
|): Chains filters together. The output of the filter on the left becomes the input for the filter on the right. - Comma (
,): Combines results. Iffilter1producesnresults andfilter2producesmresults,filter1, filter2producesn + mresults. - Construction (
{key: value, ...}or[value, ...]): Creates new JSON objects or arrays. - Map (
.[] | ...): Iterates over the elements of an array or the values of an object.
Commands / Usage
Basic Navigation & Selection
-
Output the entire JSON:
echo '{"name": "Alice", "age": 30}' | jq '.'{ "name": "Alice", "age": 30 }Outputs the input JSON as-is.
-
Select a top-level key:
echo '{"name": "Alice", "age": 30}' | jq '.name'"Alice"Extracts the value associated with the "name" key.
-
Select a nested key:
echo '{"user": {"name": "Bob", "id": 123}}' | jq '.user.name'"Bob"Extracts the value associated with the nested "name" key.
-
Select an array element by index:
echo '{"users": ["Alice", "Bob", "Charlie"]}' | jq '.users[1]'"Bob"Extracts the second element (index 1) from the "users" array.
-
Select the last array element:
echo '{"users": ["Alice", "Bob", "Charlie"]}' | jq '.users[-1]'"Charlie"Extracts the last element from the "users" array.
-
Select a range of array elements (slice):
echo '{"numbers": [0, 1, 2, 3, 4, 5]}' | jq '.numbers[1:4]'[ 1, 2, 3 ]Extracts elements from index 1 up to (but not including) index 4.
-
Select all elements of an array:
echo '{"users": [{"name": "Alice"}, {"name": "Bob"}]}' | jq '.users[]'{ "name": "Alice" } { "name": "Bob" }Outputs each element of the "users" array on a new line.
-
Select a key from all elements of an array:
echo '{"users": [{"name": "Alice"}, {"name": "Bob"}]}' | jq '.users[].name'"Alice" "Bob"Extracts the "name" from each object within the "users" array.
Transformation & Construction
-
Create a new object with selected keys:
echo '{"name": "Alice", "age": 30, "city": "New York"}' | jq '{name: .name, location: .city}'{ "name": "Alice", "location": "New York" }Creates a new object containing only the "name" and "city" (renamed to "location").
-
Create a new object with computed values:
echo '{"first_name": "Alice", "last_name": "Smith"}' | jq '{full_name: (.first_name + " " + .last_name)}'{ "full_name": "Alice Smith" }Concatenates first and last names to create a "full_name" field.
-
Create a new array from array elements:
echo '{"numbers": [1, 2, 3]}' | jq '[.numbers[] * 2]'[ 2, 4, 6 ]Creates a new array where each element is doubled.
-
Create a new object from array elements:
echo '["apple", "banana"]' | jq '{fruit1: .[0], fruit2: .[1]}'{ "fruit1": "apple", "fruit2": "banana" }Creates an object using specific array indices.
-
Combine multiple results into an array:
echo '{"name": "Alice", "age": 30}' | jq '[.name, .age]'[ "Alice", 30 ]Creates an array containing the values of "name" and "age".
Filtering & Selection with Conditions
-
Select objects based on a key’s value:
echo '[{"name": "Alice", "active": true}, {"name": "Bob", "active": false}]' | jq '.[] | select(.active == true)'{ "name": "Alice", "active": true }Selects objects where the "active" key is true.
-
Select objects based on string matching:
echo '[{"city": "London"}, {"city": "Paris"}]' | jq '.[] | select(.city | startswith("L"))'{ "city": "London" }Selects objects where the "city" value starts with "L".
-
Select objects with multiple conditions (AND):
echo '[{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]' | jq '.[] | select(.age > 25 and .name == "Alice")'{ "name": "Alice", "age": 30 }Selects objects where age is greater than 25 AND name is "Alice".
-
Select objects with multiple conditions (OR):
echo '[{"city": "London"}, {"city": "Paris"}, {"city": "Rome"}]' | jq '.[] | select(.city == "London" or .city == "Paris")'{ "city": "London" } { "city": "Paris" }Selects objects where city is "London" OR "Paris".
-
Select objects containing a specific value in an array:
echo '[{"tags": ["a", "b"]}, {"tags": ["b", "c"]}]' | jq '.[] | select(.tags[] == "a")'{ "tags": [ "a", "b" ] }Selects objects where any element in the "tags" array is "a".
-
Select objects where an array contains any of a list of values (using
contains):echo '[{"tags": ["a", "b"]}, {"tags": ["c", "d"]}]' | jq '.[] | select(.tags | contains(["a", "b"]))'{ "tags": [ "a", "b" ] }Selects objects where the "tags" array contains all elements from
["a", "b"]. -
Select objects using
mapandselect:echo '{"items": [1, 2, 3, 4, 5]}' | jq '.items |= map(select(. > 2))'{ "items": [ 3, 4, 5 ] }Filters the "items" array in place, keeping only elements greater than 2.
Array & Object Manipulation
-
Add a new key-value pair to an object:
echo '{"name": "Alice"}' | jq '. + {"city": "New York"}'{ "name": "Alice", "city": "New York" }Merges the new object into the existing one.
-
Add a new key-value pair (alternative syntax):
echo '{"name": "Alice"}' | jq '.city = "New York"'{ "name": "Alice", "city": "New York" }Assigns a value to a new or existing key.
-
Update an existing key’s value:
echo '{"name": "Alice", "age": 30}' | jq '.age = 31'{ "name": "Alice", "age": 31 }Updates the value of the "age" key.
-
Remove a key from an object:
echo '{"name": "Alice", "age": 30}' | jq 'del(.age)'{ "name": "Alice" }Deletes the "age" key and its value.
-
Append an element to an array:
echo '{"list": [1, 2]}' | jq '.list += [3]'{ "list": [ 1, 2, 3 ] }Appends the element
3to the "list" array. -
Prepend an element to an array:
echo '{"list": [1, 2]}' | jq '[0] + .list'[ 0, 1, 2 ]Creates a new array with
0prepended to the original "list". -
Remove an element from an array by index:
echo '{"list": [1, 2, 3]}' | jq 'del(.list[1])'{ "list": [ 1, 3 ] }Removes the element at index 1 from the "list" array.
-
Iterate and transform array elements (map):
echo '{"numbers": [1, 2, 3]}' | jq '.numbers |= map(. * 10)'{ "numbers": [ 10, 20, 30 ] }Applies the filter
(. * 10)to each element of the "numbers" array. -
Flatten a nested array:
echo '{"nested": [[1, 2], [3, 4]]}' | jq '.nested | flatten'[ 1, 2, 3, 4 ]Removes one level of nesting from the "nested" array.
Functions & Built-ins
-
Get the length of a string, array, or object:
echo '{"name": "jq", "tags": ["cli", "json"]}' | jq '{name_len: (.name | length), tags_len: (.tags | length)}'{ "name_len": 2, "tags_len": 2 }Calculates the length of the "name" string and the "tags" array.
-
Join array elements into a string:
echo '{"words": ["hello", "world"]}' | jq '.words | join(" ")'"hello world"Joins the elements of the "words" array with a space separator.
-
Convert to uppercase:
echo '{"text": "example"}' | jq '.text | ascii_upcase'"EXAMPLE"Converts the string value to uppercase.
-
Convert to lowercase:
echo '{"text": "EXAMPLE"}' | jq '.text | ascii_downcase'"example"Converts the string value to lowercase.
-
Check if a value exists in an array:
echo '[1, 2, 3]' | jq 'contains(2)'trueReturns true if the array contains the value 2.
-
Get keys of an object:
echo '{"a": 1, "b": 2}' | jq 'keys'[ "a", "b" ]Returns an array of the object’s keys.
-
Get values of an object:
echo '{"a": 1, "b": 2}' | jq 'values'[ 1, 2 ]Returns an array of the object’s values.
-
Get key-value pairs of an object:
echo '{"a": 1, "b": 2}' | jq 'to_entries'[ { "key": "a", "value": 1 }, { "key": "b", "value": 2 } ]Converts an object into an array of key-value objects.
-
Convert array of key-value pairs back to an object:
echo '[{"key": "a", "value": 1}, {"key": "b", "value": 2}]' | jq 'from_entries'{ "a": 1, "b": 2 }Converts an array of key-value objects back into a single object.
Command Line Options
-
Read from a file:
jq '.users[].name' data.jsonProcesses the JSON data in
data.json. -
Pretty-print output (default):
echo '{"a":1,"b":2}' | jq '.'{ "a": 1, "b": 2 }Outputs JSON in a human-readable format.
-
Compact output:
echo '{"a":1,"b":2}' | jq -c '.'{"a":1,"b":2}Outputs JSON on a single line. -
Raw output (strings only):
echo '{"name": "Alice"}' | jq -r '.name'AliceOutputs the raw string value without JSON quotes. -
Slurp all input into a single array:
cat file1.json file2.json | jq -s '.'[ { ... content of file1.json ... }, { ... content of file2.json ... } ]Reads all JSON objects from the input stream and collects them into a single array.
-
Colorize output:
echo '{"a":1}' | jq '.' --color-output # or echo '{"a":1}' | jq '.' -CApplies ANSI color codes to the output for better readability in terminals.
-
Sort object keys:
echo '{"b": 2, "a": 1}' | jq --sort-keys '.' # or echo '{"b": 2, "a": 1}' | jq -S '.'{ "a": 1, "b": 2 }Sorts the keys of all objects alphabetically before output.
-
Error on invalid input:
echo '{"a":1' | jq '.' --exit-status # or echo '{"a":1' | jq '.' -eExits with status 0 if the filter produces a value other than
falseornull. Exits with status 1 if the filter producesfalseornull. Exits with status 4 if the input is invalid JSON. -
Provide input values on the command line:
jq --arg name "Bob" --arg age 40 '. | {user_name: $name, user_age: $age}' <<< '{}'{ "user_name": "Bob", "user_age": "40" }Injects values from command-line arguments into the
jqfilter.
Common Patterns
-
Extracting specific fields from an array of objects:
curl -s 'https://api.example.com/users' | jq '.[].user.name'Fetches JSON from an API and extracts the
namefield from each user object. -
Filtering and then extracting:
echo '[{"id": 1, "status": "pending"}, {"id": 2, "status": "completed"}, {"id": 3, "status": "pending"}]' | jq '.[] | select(.status == "pending") | .id'13Finds all objects with status "pending" and extracts theirids. -
Counting occurrences:
echo '[{"type": "A"}, {"type": "B"}, {"type": "A"}, {"type": "C"}, {"type": "A"}]' | jq '[.[] | .type] | group_by(.) | map({key: .[0], count: length})'[ { "key": "A", "count": 3 }, { "key": "B", "count": 1 }, { "key": "C", "count": 1 } ]Counts how many times each unique value appears in the
typefield. -
Creating a map from an array:
echo '[{"id": "user1", "name": "Alice"}, {"id": "user2", "name": "Bob"}]' | jq '[.[] | {(.id): .name}] | add'{ "user1": "Alice", "user2": "Bob" }Transforms an array of objects into a single object where keys are
ids and values arenames. -
Processing multiple JSON objects from a file (using slurp
-s):# Assume input.json contains: # {"id": 1} # {"id": 2} jq -s 'map(.id) | add' input.json3Reads multiple JSON objects from a file, treats them as an array, extracts theirids, and sums them. -
Combining data from multiple sources:
echo '{"users": ["Alice", "Bob"]}' > users.json echo '{"admins": ["Charlie"]}' > admins.json jq -s '.[0].users as $users | .[1].admins as $admins | {all_people: $users + $admins}' users.json admins.json{ "all_people": [ "Alice", "Bob", "Charlie" ] }Reads two JSON files, combines their data, and creates a new structure.
-
Using
walkfor recursive processing:echo '{"a": 1, "b": {"c": 2, "d": 3}}' | jq 'walk(if type == "number" then . * 2 else . end)'{ "a": 2, "b": { "c": 4, "d": 6 } }Recursively traverses the JSON structure and doubles all numbers.
Gotchas
-
Outputting raw strings: When you need to use
jqoutput in shell commands (e.g.,xargs), remember the-r(raw output) flag to remove the JSON string quotes.echo '{"file": "my_document.txt"}' | jq -r '.file' | xargs cat -
Handling multiple JSON objects per line: If your input has multiple JSON objects separated by newlines (not a single JSON array), use the
-s(slurp) flag to read them all into an array first.# Input: # {"id": 1} # {"id": 2} jq -s '.' input.json # Output: # [ {"id": 1}, {"id": 2} ] -
.vs.[ ]: Using.on an array outputs the array itself. Using.[]iterates over the array elements, outputting each one individually.echo '[1, 2, 3]' | jq '.' # Output: [1, 2, 3] echo '[1, 2, 3]' | jq '.[]' # Output: 1 \n 2 \n 3 -
Order of operations with
|and,: The pipe|passes the result of the left filter as input to the right. The comma,concatenates results.echo '{"a": 1, "b": 2}' | jq '.a, .b' # Output: 1 \n 2 echo '{"a": 1, "b": 2}' | jq '.a | . + 10, .b | . + 10' # Output: 11 \n 12 -
Null values:
jqfilters that don’t produce a result yieldnull. Be mindful of this when chaining operations or usingselect.echo '{"a": 1}' | jq '.b' # Output: null echo '[{"a": 1}, {"b": 2}]' | jq '.[] | select(.a)' # Output: { "a": 1 } -
--argvs.--argjson: Use--argfor strings and--argjsonfor numbers, booleans, arrays, or objects that you want to inject as JSON values.jq --arg city "London" '. + {"city": $city}' <<< '{}' # $city is treated as a string "London" jq --argjson zip 10001 '. + {"zip": $zip}' <<< '{}' # $zip is treated as a number 10001 -
try/catchfor error handling: Usetry/catchto gracefully handle potential errors within a filter, such as accessing a non-existent key.echo '[{"a": 1}, {}]' | jq '.[] | try .a catch "default_value"'1 "default_value"