# JQ Filter Writing Conventions
## Rule
Write jq filters that are readable and maintainable. Use pipe chains, handle null values with the alternative operator, and break complex filters across multiple lines.
## Format
```bash
# Simple inline
jq '.users[] | .name'
# Complex multi-line
jq '
.users[]
| select(.active == true)
| {name: .name, email: .email}
'
```
## Good Examples
```bash
# Clean pipe chains
jq '.data.users[] | select(.role == "admin") | .email' users.json
# Null handling with alternative operator
jq '.config.timeout // 30' config.json
# Object construction
jq '.[] | {
id: .id,
fullName: "\(.firstName) \(.lastName)",
active: (.status == "active")
}' users.json
# Multi-line complex filter
jq '
[.events[]
| select(.timestamp > "2024-01-01")
| {
date: .timestamp[:10],
type: .eventType,
user: .actor.login
}
]
| group_by(.date)
| map({date: .[0].date, count: length})
' events.json
```
## Bad Examples
```bash
# BAD: No null handling — crashes on missing fields
jq '.config.database.host' config.json
# If .config or .database is null, returns null silently
# Use: jq '.config.database.host // error("missing database host")'
# BAD: Overly complex one-liner
jq '[.[]|select(.active)|{n:.name,e:.email}]|sort_by(.n)|.[:10]' f.json
# Break this into a readable multi-line filter
# BAD: Unnecessary identity and redundant operations
jq '. | .users | . | .[] | . | .name' data.json
# Simplify: jq '.users[].name' data.json
```
## Enforcement
- Use multi-line format for filters longer than 80 characters
- Test filters with sample data before embedding in scripts
- Store complex filters in .jq files for reuse