Files
2025-11-30 09:06:54 +08:00

6.5 KiB

jq: JSON Query and Extraction Reference

Goal: Extract specific data from JSON without reading entire file.

The Essential Pattern

jq '.field' file.json

Use -r flag for raw output (removes quotes from strings):

jq -r '.field' file.json

Use -r by default for string values - cleaner output.


Core Patterns (80% of Use Cases)

1. Extract Top-Level Field

jq -r '.version' package.json
jq -r '.name' package.json

2. Extract Nested Field

jq -r '.dependencies.react' package.json
jq -r '.scripts.build' package.json
jq -r '.config.database.host' config.json

3. Extract Multiple Fields

jq '{name, version, description}' package.json

Creates object with just those fields.

Or as separate lines:

jq -r '.name, .version' package.json

4. Extract from Array by Index

jq '.[0]' array.json           # First element
jq '.items[2]' data.json        # Third element

5. Extract All Array Elements

jq '.[]' array.json             # All elements
jq '.items[]' data.json         # All items

6. Extract Field from Each Array Element

jq -r '.dependencies | keys[]' package.json      # All dependency names
jq -r '.items[].name' data.json                  # Name from each item

7. Filter Array by Condition

jq '.items[] | select(.active == true)' data.json
jq '.items[] | select(.price > 100)' data.json

8. Get Object Keys

jq -r 'keys[]' object.json
jq -r '.dependencies | keys[]' package.json

9. Check if Field Exists

jq 'has("field")' file.json

10. Handle Missing Fields (Use // for Default)

jq -r '.field // "default"' file.json

Common Real-World Workflows

"What version is this package?"

jq -r '.version' package.json

"What's the main entry point?"

jq -r '.main' package.json

"List all dependencies"

jq -r '.dependencies | keys[]' package.json

"What version of React?"

jq -r '.dependencies.react' package.json

"List all scripts"

jq -r '.scripts | keys[]' package.json

"Get specific script command"

jq -r '.scripts.build' package.json

"Check TypeScript compiler options"

jq '.compilerOptions' tsconfig.json

"Get target from tsconfig"

jq -r '.compilerOptions.target' tsconfig.json

"List all services from docker-compose JSON"

jq -r '.services | keys[]' docker-compose.json

"Get environment variables for a service"

jq '.services.api.environment' docker-compose.json

Advanced Patterns (20% Use Cases)

Combine Multiple Queries

jq '{version, deps: (.dependencies | keys)}' package.json

Map Array Elements

jq '[.items[] | .name]' data.json          # Array of names

Count Array Length

jq '.items | length' data.json
jq '.dependencies | length' package.json

Sort Array

jq '.items | sort_by(.name)' data.json

Group and Transform

jq 'group_by(.category)' data.json

Complex Filter

jq '.items[] | select(.active and .price > 100) | .name' data.json

Pipe Composition

jq uses | for piping within queries:

jq '.items | map(.name) | sort' data.json

Can also pipe to shell commands:

jq -r '.dependencies | keys[]' package.json | wc -l     # Count dependencies
jq -r '.dependencies | keys[]' package.json | sort      # Sorted dependency list

Common Flags

  • -r - Raw output (no quotes) - USE THIS FOR STRINGS
  • -c - Compact output (single line)
  • -e - Exit with error if output is false/null
  • -S - Sort object keys
  • -M - Monochrome (no colors)

Default to -r for string extraction.


Handling Edge Cases

If Field Might Not Exist

jq -r '.field // "not found"' file.json

If Result Might Be Null

jq -r '.field // empty' file.json          # Output nothing if null

If Array Might Be Empty

jq -r '.items[]? // empty' file.json       # ? suppresses errors

Multiple Possible Paths

jq -r '.field1 // .field2 // "default"' file.json

Error Handling

If field doesn't exist:

# BAD: jq '.nonexistent' file.json
# → null (but no error)

# GOOD: Check existence first
jq -e 'has("field")' file.json && jq '.field' file.json

Or use default:

jq -r '.field // "not found"' file.json

Integration with Other Tools

With ast-grep

# Get dependencies, then search code for usage
jq -r '.dependencies | keys[]' package.json | while read dep; do
  rg -l "from ['\"]$dep['\"]"
done

With Edit Tool

Common workflow:

  1. Use jq to extract current value
  2. Modify value
  3. Use Edit tool to update JSON (or jq for complex updates)

Reading STDIN

echo '{"key":"value"}' | jq -r '.key'

Best Practices

1. Always Use -r for String Fields

# BAD:  jq '.version' package.json  → "1.0.0" (with quotes)
# GOOD: jq -r '.version' package.json  → 1.0.0 (raw)

2. Test Queries on Small Examples First

echo '{"test":"value"}' | jq -r '.test'

3. Use // for Defaults

jq -r '.field // "default"' file.json

4. Use keys[] for Object Properties

jq -r 'keys[]' object.json

5. Combine with Shell Pipes

jq -r '.dependencies | keys[]' package.json | grep react

Quick Reference

Most Common Commands

# Single field
jq -r '.field' file.json

# Nested field
jq -r '.parent.child' file.json

# Array element
jq '.array[0]' file.json

# All array elements
jq '.array[]' file.json

# Object keys
jq -r 'keys[]' file.json

# Filter array
jq '.array[] | select(.field == "value")' file.json

# Multiple fields
jq '{field1, field2}' file.json

# With default
jq -r '.field // "default"' file.json

When to Use Read Instead

Use Read tool when:

  • File is < 50 lines
  • Need to see overall structure
  • Making edits (need full context)
  • Exploring unknown JSON structure

Use jq when:

  • File is large
  • Know exactly what field(s) are needed
  • Want to save context tokens

Summary

Default pattern:

jq -r '.field' file.json

Key principles:

  1. Use -r for string output (raw, no quotes)
  2. Use . notation for nested fields
  3. Use [] for array access
  4. Use // for defaults
  5. Use keys[] for object properties
  6. Pipe with | inside jq, pipe to shell after

Massive context savings: Extract only what is needed instead of reading entire JSON files.