jq — Consultas y Transformación de JSON
Regla de Lectura Selectiva
Comience con:
references/senior-master-standard.mdreferences/usage-routing.mdreferences/quality-checklist.md
Luego cargue solo los documentos heredados, scripts, activos o ejemplos que coincidan con la tarea real del usuario.
Descripción General
jq es la herramienta CLI estándar para consultar y remodelar JSON. Este skill cubre un uso práctico y de nivel experto: filtrar datos profundamente anidados, transformar estructuras, agregar valores y componer jq en pipelines de shell. Cada ejemplo está listo para copiar y pegar en flujos de trabajo reales.
Cuándo Usar Este Skill
- Úselo al analizar la salida JSON de APIs, herramientas CLI (AWS, GitHub, kubectl, docker) o archivos de registro
- Úselo al transformar la estructura JSON (renombrar claves, aplanar arreglos, agrupar registros)
- Úselo cuando el usuario necesite
jqdentro de un script bash o una línea de comando - Úselo al explicar qué hace una expresión compleja de
jq
Cómo Funciona
jq toma una expresión de filtro y la aplica a la entrada JSON. Los filtros se componen con tuberías (|), y jq maneja de forma nativa arreglos, objetos, cadenas, números, booleanos y null.
Selección Básica
# Extraer un campo
echo '{"name":"alice","age":30}' | jq '.name'
# "alice"
# Acceso anidado
echo '{"user":{"email":"[email protected]"}}' | jq '.user.email'
# Índice de arreglo
echo '[10, 20, 30]' | jq '.[1]'
# 20
# Segmento de arreglo
echo '[1,2,3,4,5]' | jq '.[2:4]'
# [3, 4]
# Todos los elementos del arreglo
echo '[{"id":1},{"id":2}]' | jq '.[]'
Filtrado con select
# Conservar solo los elementos que coinciden
echo '[{"role":"admin"},{"role":"user"},{"role":"admin"}]' \
| jq '[.[] | select(.role == "admin")]'
# Comparación numérica
curl -s https://api.github.com/repos/owner/repo/issues \
| jq '[.[] | select(.comments > 5)]'
# Verificar que un campo existe y no es nulo
jq '[.[] | select(.email != null)]'
# Combinar condiciones
jq '[.[] | select(.active == true and .score >= 80)]'
Mapeo y Transformación
# Extraer un campo de cada elemento del arreglo
echo '[{"name":"alice","age":30},{"name":"bob","age":25}]' \
| jq '[.[] | .name]'
# ["alice", "bob"]
# Abreviatura: map()
jq 'map(.name)'
# Construir un nuevo objeto por elemento
jq '[.[] | {user: .name, years: .age}]'
# Agregar un campo calculado
jq '[.[] | . + {senior: (.age > 28)}]'
# Renombrar claves
jq '[.[] | {username: .name, email_address: .email}]'
Agregación y Reducción
# Sumar todos los valores
echo '[1, 2, 3, 4, 5]' | jq 'add'
# 15
# Sumar un campo entre objetos
jq '[.[].price] | add'
# Contar elementos
jq 'length'
# Máximo / mínimo
jq 'max_by(.score)'
jq 'min_by(.created_at)'
# reduce: acumulador personalizado
echo '[1,2,3,4,5]' | jq 'reduce .[] as $x (0; . + $x)'
# 15
# Agrupar por campo
jq 'group_by(.department)'
# Contar por grupo
jq 'group_by(.status) | map({status: .[0].status, count: length})'
Interpolación de Cadenas y Formateo
# Interpolación de cadenas
jq -r '.[] | "\(.name) tiene \(.age) años"'
# Formatear como CSV (sin encabezado)
jq -r '.[] | [.name, .age, .email] | @csv'
# Formatear como TSV
jq -r '.[] | [.name, .score] | @tsv'
# Codificar URL
jq -r '.query | @uri'
# Codificar Base64
jq -r '.data | @base64'
Trabajar con Claves y Rutas
# Listar todas las claves de nivel superior
jq 'keys'
# Verificar si existe una clave
jq 'has("email")'
# Eliminar una clave
jq 'del(.password)'
# Eliminar claves anidadas de cada elemento
jq '[.[] | del(.internal_id, .raw_payload)]'
# Descenso recursivo: encontrar todos los valores de una clave en cualquier lugar del árbol
jq '.. | .id? // empty'
# Obtener todas las rutas hoja
jq '[paths(scalars)]'
Condicionales y Manejo de Errores
# if-then-else
jq 'if .score >= 90 then "A" elif .score >= 80 then "B" else "C" end'
# Operador alternativo: usar valor por defecto si es nulo o falso
jq '.nickname // .name'
# try-catch: omitir errores en lugar de detenerse
jq '[.[] | try .nested.value catch null]'
# Suprimir salida nula con // empty
jq '.[] | .optional_field // empty'
Integración Práctica con el Shell
# Leer desde un archivo
jq '.users' data.json
# Salida compacta (sin espacios) para seguir tuberías
jq -c '.[]' records.json | while IFS= read -r record; do
echo "Procesando: $record"
done
# Pasar una variable de shell a jq
STATUS="active"
jq --arg s "$STATUS" '[.[] | select(.status == $s)]'
# Pasar un número
jq --argjson threshold 42 '[.[] | select(.value > $threshold)]'
# Leer múltiples líneas JSON en un arreglo
jq -s '.' records.ndjson
# Múltiples archivos: leer todos en un solo arreglo
jq -s 'add' file1.json file2.json
# Pipeline null-safe desde un comando
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'
# CLI de GitHub: extraer números de PR
gh pr list --json number,title | jq -r '.[] | "\(.number)\t\(.title)"'
# CLI de AWS: listar IDs de instancias en ejecución
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[] | select(.State.Name=="running") | .InstanceId'
# Docker: mostrar nombres de contenedores e imágenes
docker inspect $(docker ps -q) | jq -r '.[] | "\(.Name)\t\(.Config.Image)"'
Patrones Avanzados
# Transponer un objeto de arreglos a un arreglo de objetos
# Entrada: {"names":["a","b"],"scores":[10,20]}
jq '[.names, .scores] | transpose | map({name: .[0], score: .[1]})'
# Aplanar un nivel
jq 'flatten(1)'
# Únicos por campo
jq 'unique_by(.email)'
# Ordenar, eliminar duplicados y reindexar
jq '[.[] | .name] | unique | sort'
# walk: aplicar transformación a cada nodo recursivamente
jq 'walk(if type == "string" then ascii_downcase else . end)'
# env: leer variables de entorno dentro de jq
export API_KEY=secret
jq -n 'env.API_KEY'
Buenas Prácticas
- Siempre use
-r(salida sin formato) cuando pase resultados dejqa variables de shell u otros comandos para eliminar las comillas de las cadenas JSON - Use
--arg/--argjsonpara inyectar variables de shell de manera segura — nunca interpole variables de shell directamente en las cadenas de filtro - Prefiera
map(f)sobre[.[] | f]para mayor legibilidad - Use
-c(compacto) para pipelines JSON delimitados por nueva línea; omítalo para depuración legible - Pruebe los filtros de forma interactiva con
jq -ny entrada literal antes de incrustarlos en scripts - Use
emptypara descartar elementos no deseados en lugar de filtrar anull
Notas de Seguridad
jqes de solo lectura por diseño — no puede escribir archivos ni ejecutar comandos- Evite incrustar valores de campo JSON no confiables directamente en comandos de shell; siempre use comillas o
--arg
Errores Comunes
-
Problema:
jqdevuelvenullen lugar del valor esperado Solución: Verifique errores tipográficos en los nombres de las claves; usekeyspara inspeccionar los nombres de campo reales. Recuerde que JSON distingue entre mayúsculas y minúsculas. -
Problema: Los números aparecen entre comillas como cadenas en la salida Solución: Use
--argjsonen lugar de--argal inyectar valores numéricos. -
Problema: El filtro funciona en la terminal pero falla en un script Solución: Asegúrese de que la cadena del filtro utilice comillas simples en el shell para evitar la expansión de variables. Ejemplo:
jq '.field'nojq ".field". -
Problema:
adddevuelvenullen un arreglo vacío Solución: Useadd // 0oadd // ""para proporcionar un valor predeterminado. -
Problema: La transmisión de archivos grandes es lenta Solución: Use
jq --streamo cambie ajstream/gronpara archivos muy grandes.
Habilidades Relacionadas
@bash-pro— Envolver llamadas jq en scripts de shell robustos@bash-linux— Patrones generales de pipelines de shell@github-automation— Usar jq con la salida JSON de GitHub CLI
Limitaciones
- Use este skill solo cuando la tarea coincida claramente con el alcance descrito anteriormente.
- No trate la salida como un sustituto de la validación, prueba o revisión experta específica del entorno.
- Deténgase y solicite aclaración si faltan entradas requeridas, permisos, límites de seguridad o criterios de éxito.