Editores, línea de comandos y cadenas de herramientas de automatización
En resumen: Los editores resuelven "verlo con claridad, editarlo correctamente", mientras que la línea de comandos resuelve "lotes, repetible". Cada lado tiene unas pocas herramientas que siguen siendo útiles una década después.

En resumen: elige el editor según el escenario — CodeMirror 6 para sitios utilitarios y móvil, Monaco solo cuando necesites la experiencia completa de un IDE; deja el trabajo por lotes a jq más tres comprobaciones de CI para sintaxis, estructura y estilo, y pasa siempre los argumentos con jq --arg.
La era de comprobar JSON a mano debería haber terminado: cualquier cosa que una máquina pueda repetir, no la dejes a los ojos humanos.
1. Editores en el navegador
1.1 Integración mínima de CodeMirror 6
import { EditorView, basicSetup } from 'codemirror';
import { json, jsonParseLinter } from '@codemirror/lang-json';
import { linter, lintGutter } from '@codemirror/lint';
const view = new EditorView({
parent: document.getElementById('editor')!,
doc: '{"hello": "json"}',
extensions: [
basicSetup,
json(),
linter(jsonParseLinter()),
lintGutter(),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
// Aplica debounce antes de hacer trabajo pesado; no formatees en cada pulsación
scheduleParse(update.state.doc.toString());
}
}),
],
});
Cuatro puntos que conviene tener en cuenta:
json()proporciona resaltado de sintaxis y emparejamiento de corchetes — no escribas el tuyo;jsonParseLinter()produce marcadores de error a nivel de línea/columna; combínalo conlintGutter()para mostrar iconos junto a los números de línea;- El
updateListenerdebe llevar debounce; llamar aJSON.parsesobre cien mil líneas en cada pulsación provocará un retraso visible; - Los documentos grandes necesitan optimizaciones más allá de
EditorView.lineWrappingpara evitar renderizarlo todo de golpe (CodeMirror 6 renderiza por viewport de forma predeterminada, lo que supone una mejora frente a versiones anteriores).
1.2 Plegado y esquemas
CodeMirror 6 tiene plegado integrado; en escenarios JSON normalmente se pliega por "objeto/array":
import { foldGutter, foldKeymap } from '@codemirror/language';
import { keymap } from '@codemirror/view';
Con foldGutter() y keymap.of(foldKeymap), los usuarios pueden contraer arrays largos con un atajo de teclado.
1.3 Elegir entre CodeMirror y Monaco
| Dimensión | CodeMirror 6 | Monaco |
|---|---|---|
| Tamaño del bundle | Pequeño, modular | Grande (varios MB) |
| Móvil | Bien soportado | Experiencia mediocre |
| Servicios de lenguaje | Hay que construirlos | Ricos, integrados |
| Coste de personalización | Bajo | Medio |
Sitios utilitarios y móvil primero → CodeMirror; experiencia completa de IDE (varios archivos, ir a la definición, autocompletado) → Monaco.
2. Línea de comandos: seis recetas de jq de alta frecuencia
jq es al JSON lo que sed + awk al texto; aprender solo una pequeña parte de su sintaxis cubre el ochenta por ciento de las necesidades diarias.
# 1. Seleccionar campos (lo más común)
jq '.data.items[].name' response.json
# 2. Filtrar + remodelar
jq '.data.items[] | select(.price < 10) | {id, price}' response.json
# 3. Agregados (length, sum, max)
jq '[.items[] | .price] | {count: length, total: add, max: max}' response.json
# 4. Agrupar y agregar
jq '[.items[]] | group_by(.category) | map({category: .[0].category, count: length})' response.json
# 5. Combinar varios archivos en un array
jq -s '.' part-*.json > merged.json
# 6. Procesar JSON Lines línea a línea
jq -c 'select(.level == "error")' app.jsonl
# Opciones de salida habituales
jq -r '.data.name' # Quita las comillas para que se pueda encadenar a la shell
jq -c '.' # Salida compacta, una línea
jq --arg id "$ID" '.id == $id' # Pasa argumentos de forma segura, evitando inyección por concatenación
--arg merece una mención especial: concatenar una variable directamente en una expresión falla en cuanto el valor contiene comillas, mientras que --arg deja que jq gestione el escapado.
2.1 Otras herramientas de un vistazo
| Herramienta | Propósito | En una frase |
|---|---|---|
yq |
Conversión YAML/JSON/XML | Sintaxis similar a jq, el caballo de batalla de los archivos de configuración |
dasel |
Consulta unificada entre formatos | Soporta JSON/YAML/TOML/XML/CSV |
fx |
Navegación interactiva de JSON | Haz clic en la terminal, bueno para explorar |
jless |
Navegación paginada en la terminal | Como less, con plegado y búsqueda |
gron |
Aplana JSON en líneas consultables con grep | Una gran herramienta para averiguar "en qué nivel está este campo" |
ajv-cli |
Validación con schema | Valida archivos JSON en CI |
La idea detrás de gron merece conocerse en especial:
$ echo '{"a":{"b":[1,2]}}' | gron
json = {};
json.a = {};
json.a.b = [];
json.a.b[0] = 1;
json.a.b[1] = 2;
Una vez aplanado, grep puede localizar la ruta, lo que es mucho más rápido que expandir nivel a nivel en un editor.
3. Tres capas de validación en CI
| Capa | Herramienta | Qué significa un fallo |
|---|---|---|
| Sintaxis | JSON.parse / jq empty |
El archivo en sí está malformado |
| Estructura | ajv-cli + schema |
Faltan campos, tipos incorrectos |
| Estilo | Prettier | Formato inconsistente, diffs ruidosos |
# Sintaxis: valida por lotes todos los archivos json del repositorio
find . -name '*.json' -not -path './node_modules/*' -print0 \
| xargs -0 -n1 jq empty
# Estructura: valida contra un schema
npx ajv-cli validate -s schemas/order.json -d 'fixtures/orders/*.json' --strict=false
# Estilo: solo comprobar, no modificar
npx prettier --check "**/*.json"
Necesitas las tres capas, porque sus mensajes de error son completamente distintos:
jq empty solo dice "qué línea está rota", ajv dice "qué campo viola qué palabra clave" y Prettier solo dice "el formato es inconsistente".
4. Hooks de pre-commit
# Ejemplo de .husky/pre-commit (extracto)
npx lint-staged
{
"lint-staged": {
"*.json": ["prettier --write", "jq empty"]
}
}
Ten cuidado con los archivos de configuración de herramientas como package.json y tsconfig.json; no dejes que Prettier los reindente a la ligera —
algunas herramientas son sensibles al formato (el JSON válido no debería serlo, pero en la práctica esto ha causado problemas). Puedes excluirlos individualmente.
5. Consejos de depuración
- Usa
jq -ecomo aserción: el código de salida es 1 cuando el resultado de la expresión esfalseonull, así que puede entrar directamente en scripts como comprobación; jq 'paths'lista todas las rutas, dándote una visión rápida de la estructura de un documento desconocido;jq '.. | objects | keys'encuentra todos los nombres de clave que han aparecido alguna vez, útil para cazar grafías inconsistentes;- Formatea antes de comparar en el editor: un diff sin formatear es ruido puro; una comparación estructural como
/diffes más precisa.
6. Lista de comprobación
- [ ] Los marcadores de error del editor son precisos hasta línea y columna, y el parseo tiene debounce;
- [ ] Los scripts del equipo pasan argumentos con
jq --argen lugar de concatenar cadenas; - [ ] CI tiene las tres capas de validación (sintaxis/estructura/estilo);
- [ ] pre-commit solo procesa archivos en staging, para que un escaneo completo no ralentice los commits;
- [ ] Las versiones de las herramientas están fijadas en
package.jsono.tool-versions.
FAQ
¿Cómo elijo entre CodeMirror 6 y Monaco?
Para sitios utilitarios y móvil, prefiere CodeMirror 6: es pequeño, modular y está bien soportado en móvil, y el resaltado de sintaxis, el emparejamiento de corchetes y el plegado se pueden componer según necesidad. Recurre a Monaco solo cuando necesites la experiencia completa de IDE con varios archivos, ir a la definición y autocompletado, a costa de un bundle de varios megabytes y un mayor esfuerzo de personalización.
¿Por qué CI necesita las comprobaciones de sintaxis, estructura y estilo juntas?
Las tres capas reportan errores completamente distintos: jq empty dice qué línea está rota, ajv dice qué campo viola qué palabra clave y Prettier solo dice que el formato es inconsistente. Eliminar una capa hace que los errores de las otras se malinterpreten fácilmente, así que mantén las tres y detente en cuanto falle una.
¿Debería confiar en pre-commit en lugar de validar en CI?
No. Los hooks procesan solo archivos en staging, lo que da feedback en un minuto pero no puede cubrir todo el repositorio ni los cambios que se saltan el commit. CI es responsable de la exhaustividad: mantén pre-commit sobre los archivos en staging y deja los escaneos completos a CI.