Saltar al contenido principal

Clase 09 — Validación, Errores Comunes y Buenas Prácticas

Herramientas de validación

# jq (la más usada)
jq empty archivo.json && echo "✅ Válido" || echo "❌ Inválido"

# python3
python3 -m json.tool archivo.json
python3 -c "import json; json.load(open('archivo.json'))" && echo "✅" || echo "❌"

# jsonlint (Node.js)
npm install -g jsonlint
jsonlint archivo.json

Validar en CI/CD

name: JSON Lint
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validar todos los JSON
run: |
errores=0
for f in $(find . -name "*.json" -not -path "./node_modules/*"); do
if ! jq empty "$f" 2>/dev/null; then
echo "❌ JSON inválido: $f"; ((errores++))
else
echo "✅ $f"
fi
done
[[ $errores -gt 0 ]] && exit 1

Errores comunes

1. Coma trailing

// ❌ ERROR
{ "nombre": "Ana", "edad": 28, }

// ✅ CORRECTO
{ "nombre": "Ana", "edad": 28 }

2. Comillas simples

// ❌ ERROR
{ 'nombre': 'Ana' }

// ✅ CORRECTO
{ "nombre": "Ana" }

3. Claves sin comillas

// ❌ ERROR (esto es JavaScript, no JSON)
{ nombre: "Ana" }

// ✅ CORRECTO
{ "nombre": "Ana" }

4. Comentarios

// ❌ ERROR — JSON no soporta comentarios
{ "nombre": "Ana" /* comentario */ }

// ✅ ALTERNATIVA — Campo de documentación
{ "_comment": "Configuración del servidor", "nombre": "Ana" }

5. Strings multilínea

// ❌ ERROR
{ "mensaje": "línea 1
línea 2" }

// ✅ CORRECTO — Usar \n
{ "mensaje": "línea 1\nlínea 2" }

6. Valores no válidos

// ❌ ERROR: undefined, Infinity, NaN, funciones
// ✅ CORRECTO: usar null en su lugar

7. Encoding BOM

# Detectar BOM
file archivo.json

# Remover BOM
sed -i '1s/^\xEF\xBB\xBF//' archivo.json

Buenas prácticas

1. Indentación de 2 espacios

2. Nombres de claves consistentes

// ✅ snake_case (común en Python, APIs REST)
{ "user_name": "ana", "created_at": "2026-02-20" }

// ✅ camelCase (común en JavaScript)
{ "userName": "ana", "createdAt": "2026-02-20" }

// ❌ EVITAR mezclar estilos

3. Usar tipos apropiados

// ❌ Tipos incorrectos
{ "puerto": "8080", "activo": "true" }

// ✅ Tipos correctos
{ "puerto": 8080, "activo": true }

4. Fechas en formato ISO 8601

{ "creado": "2026-02-20T15:30:00Z" }

5. Respuestas de API consistentes

// Éxito
{ "status": "success", "code": 200, "data": { "id": 1, "nombre": "Pikachu" } }

// Error
{ "status": "error", "code": 404, "error": { "message": "Pokémon no encontrado" } }

6. JSON Schema para validar estructura

{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Servidor",
"type": "object",
"required": ["hostname", "ip", "puerto"],
"properties": {
"hostname": { "type": "string", "pattern": "^[a-z][a-z0-9-]+$" },
"ip": { "type": "string", "format": "ipv4" },
"puerto": { "type": "integer", "minimum": 1, "maximum": 65535 },
"ssl": { "type": "boolean", "default": false }
}
}

Cheat Sheet — Referencia rápida

TIPOS:     "string" | 42 | 3.14 | true/false | null | {} | []
REGLAS: ✅ Comillas dobles | ✅ Coma entre elementos | ❌ Sin comentarios | ❌ Sin coma trailing

jq BÁSICO:
jq '.' → Pretty print
jq '.campo' → Acceder campo
jq '.[0]' → Primer elemento
jq '.[]' → Iterar array
jq 'length' → Longitud
jq 'keys' → Listar claves
jq 'map(.campo)' → Transformar
jq 'select(.x == "y")' → Filtrar
jq 'sort_by(.campo)' → Ordenar
jq 'group_by(.campo)' → Agrupar
jq -r → Sin comillas
jq -c → Compacto
jq empty → Solo validar