jq JSON Processor

jq cheatsheet — filter, transform, extract JSON from the command line. .field, .[] , select(), map(), keys, @csv. Every jq expression with real examples.

11 min read

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: jq operates 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. start is inclusive, end is 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. If filter1 produces n results and filter2 produces m results, filter1, filter2 produces n + m results.
  • 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 map and select:

    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 3 to the "list" array.

  • Prepend an element to an array:

    echo '{"list": [1, 2]}' | jq '[0] + .list'
    
    [
      0,
      1,
      2
    ]
    

    Creates a new array with 0 prepended 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)'
    
    true
    

    Returns 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.json
    

    Processes 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'
    

    Alice Outputs 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 '.' -C
    

    Applies 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 '.' -e
    

    Exits with status 0 if the filter produces a value other than false or null. Exits with status 1 if the filter produces false or null. 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 jq filter.

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 name field 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'
    

    1 3 Finds all objects with status "pending" and extracts their ids.

  • 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 type field.

  • 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 are names.

  • Processing multiple JSON objects from a file (using slurp -s):

    # Assume input.json contains:
    # {"id": 1}
    # {"id": 2}
    jq -s 'map(.id) | add' input.json
    

    3 Reads multiple JSON objects from a file, treats them as an array, extracts their ids, 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 walk for 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 jq output 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: jq filters that don’t produce a result yield null. Be mindful of this when chaining operations or using select.

    echo '{"a": 1}' | jq '.b' # Output: null
    echo '[{"a": 1}, {"b": 2}]' | jq '.[] | select(.a)' # Output: { "a": 1 }
    
  • --arg vs. --argjson: Use --arg for strings and --argjson for 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/catch for error handling: Use try/catch to 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"