Skip to content
Volver al blog
Tutoriales

El problema Norway de YAML y las diferencias JSON-YAML

Por qué YAML lee "no" como false. Interrupciones reales en K8s por entrecomillado de cadenas. Diferencias JSON vs YAML, reglas de sangría y conversión de manifiestos K8s explicadas.

14 min de lectura

El problema Norway de YAML y las diferencias JSON ↔ YAML que todo ingeniero debería conocer

Era un despliegue Helm rutinario. El equipo había pasado dos días ajustando un archivo values.yaml para un lanzamiento multi-región. El chart creaba con plantilla un ConfigMap de Kubernetes con metadatos de localización — incluyendo el código de país para su centro de datos en Noruega. Alguien escribió country: NO y lo confirmó. El pipeline de CI se puso en verde. El despliegue salió.

Entonces llegaron las alertas.

El ConfigMap contenía country: false en lugar de country: "NO". Cada servicio posterior que leía el campo country obtenía un booleano en vez de una cadena. La comparación de cadenas falló. La lógica de enrutamiento cayó a un valor predeterminado. El tráfico que debería haberse quedado en Noruega acabó siendo procesado por el endpoint regional incorrecto.

La causa raíz fue una única cadena sin entrecomillar en un archivo YAML. YAML 1.1 — la versión que prácticamente todas las herramientas de Kubernetes usan — trata NO como el booleano false. Trata YES, ON, OFF, Y, N, no, yes, on, off, y, n y una docena de variantes más de la misma manera. Sin advertencia. Sin error. Silenciosamente incorrecto.

JSON no tiene este problema. {"country": "NO"} es siempre una cadena. La coerción implícita de tipos de YAML es a la vez su mayor comodidad y su trampa más peligrosa.

Esta guía cubre el panorama completo: por qué existe el problema Norway, qué cambió en YAML 1.2 (y por qué la mayoría de las herramientas lo ignoran), cómo escribir estrategias de entrecomillado correctas, las reglas de sangría que confunden a los recién llegados, las trampas de precisión numérica y cuatro escenarios reales de conversión desde manifiestos de Kubernetes hasta planes de Terraform. Cuando necesites aplanar un valor JSON en YAML de forma segura sin esta trampa, nuestro convertidor de JSON a YAML entrecomilla automáticamente las cadenas propensas al problema Norway.

JSON vs YAML — Cuándo usar cuál

Antes de entrar en profundidad en el problema Norway, es útil entender para qué está optimizado cada formato. No son intercambiables — cada uno tiene un diseño central que lo hace la mejor opción en contextos específicos.

DimensiónJSONYAML
SintaxisEstricta — llaves, comillas, comas requeridasFlexible — basada en sangría, puntuación mínima
Sistema de tiposExplícito: cadena, número, booleano, null, array, objetoImplícito — YAML 1.1 infiere tipos a partir de la forma del valor
Legibilidad humanaAmigable para desarrolladores, verificable por máquinasAmigable para humanos, fácil de editar a mano
Requisito de comillasLas cadenas siempre van entrecomilladasLa mayoría de los escalares pueden ir sin comillas (el origen del problema Norway)
ComentariosNo admitidosAdmitidos con #
Uso principalAPIs, intercambio de datos, sistemas de configuración modernosKubernetes, Docker Compose, Ansible, pipelines de CI
Análisis sorprendenteNinguno — análisis estrictoSí — Norway, octal, marcas de tiempo
Aplicación de esquemasEcosistema JSON SchemaYAML Schema (menos herramientas)

JSON gana cuando tus datos cruzan fronteras de sistemas — APIs REST, colas de mensajes, serialización de bases de datos. Las máquinas lo analizan, las máquinas lo generan, y la sintaxis estricta hace que la validación sea sencilla. Usa un Formateador JSON para validar la estructura antes de enviarlo.

YAML gana cuando los humanos son los autores principales. Los manifiestos de Kubernetes, los workflows de GitHub Actions, los charts de Helm, los playbooks de Ansible — estos son archivos que los desarrolladores leen y editan docenas de veces. La puntuación reducida y el soporte para comentarios los hace genuinamente más mantenibles que sus equivalentes en JSON.

El problema surge en la frontera: cuando una herramienta genera JSON (como kubectl get deploy -o json o terraform show -json) y un humano necesita versionar o editar el resultado como YAML. Esa conversión es donde vive el problema Norway. Nuestro convertidor de YAML a JSON gestiona la dirección inversa cuando necesitas volver.

El problema Norway — Análisis en profundidad

El problema Norway no es un error. Es una característica de la especificación YAML 1.1 que se comporta exactamente como fue diseñada. Entender por qué fue diseñada así — y por qué tantos sistemas aún implementan 1.1 — es la clave para evitarlo.

Por qué “no”, “yes”, “on”, “off”, “y”, “n” se analizan incorrectamente

La especificación YAML 1.1 definió un tipo booleano amplio que pretendía ser amigable para los humanos. Reconocía todos los siguientes como true o false:

Verdadero: y, Y, yes, Yes, YES, true, True, TRUE, on, On, ON

Falso: n, N, no, No, NO, false, False, FALSE, off, Off, OFF

La intención era buena: los archivos de configuración a menudo usan yes/no en lugar de true/false en inglés, y YAML quería apoyar la forma natural en que las personas escriben la configuración. El problema es que yes, no, on, off, y y n también son valores de cadena perfectamente legítimos que significan algo completamente diferente en la mayoría de las aplicaciones.

Aquí está la discrepancia en YAML concreto:

# YAML 1.1 (lo que implementa la mayoría de los parsers)
country: NO        # se analiza como: country: false   ← PELIGRO
enabled: yes       # se analiza como: enabled: true
restart: off       # se analiza como: restart: false
language: y        # se analiza como: language: true
shell: n           # se analiza como: shell: false

# Correcto — las comillas explícitas de cadena anulan la inferencia de tipos
country: "NO"      # se analiza como: country: "NO"    ← seguro
enabled: "yes"     # se analiza como: enabled: "yes"
restart: "off"     # se analiza como: restart: "off"
language: "y"      # se analiza como: language: "y"
shell: "n"         # se analiza como: shell: "n"

Y la comparación con JSON:

{"country": "NO"}

En JSON, NO entre comillas es siempre e incondicionalmente una cadena. No existe inferencia implícita de tipos. La estrictez que hace que JSON parezca verboso es también lo que lo hace seguro.

Más allá de la coerción booleana, YAML 1.1 también convierte implícitamente:

  • 123e4 → el número 1230000 (notación científica)
  • 0x1A → el número 26 (hexadecimal)
  • 0755 → el número 493 (octal — este rompe las cadenas de permisos de archivo de Unix)
  • 2024-05-04 → un objeto de fecha en muchos parsers (no solo una cadena)
  • 1_000_000 → el número 1000000 (separador de guión bajo)

El problema Norway es realmente solo el miembro más famoso de toda una familia de coerciones implícitas de tipos en YAML.

YAML 1.1 vs 1.2 — Qué cambió

YAML 1.2 se publicó en 2009 — cuatro años después de YAML 1.1. Su objetivo principal era alinear estrictamente YAML con JSON (ya que JSON es en realidad un subconjunto válido de YAML 1.2) y reducir las sorprendentes conversiones implícitas de tipos.

En YAML 1.2:

  • El booleano se reduce exactamente a true y false (sensibles a mayúsculas). Eso es todo. yes, no, on, off son cadenas simples.
  • Los literales octales requieren el prefijo 0o (0o755) — la antigua forma 0755 es una cadena.
  • Las marcas de tiempo no se analizan implícitamente — 2024-05-04 se mantiene como una cadena a menos que lo etiquetes explícitamente.
  • La especificación misma es un superconjunto de JSON, lo que significa que todo documento JSON válido es YAML 1.2 válido.

En papel, YAML 1.2 resuelve el problema Norway por completo. En la práctica, el ecosistema apenas se movió.

LibreríaEspecificación predeterminadaRiesgo Norway
PyYAML (Python)YAML 1.1Sí — yaml.safe_load aún analiza NO como False
ruamel.yaml (Python)YAML 1.2 (opcional)Configurable — más seguro por defecto
js-yaml (Node.js)YAML 1.1Sí en versiones antiguas; las versiones más recientes tienen la opción FAILSAFE_SCHEMA
eemeli/yaml (Node.js)YAML 1.2No — 1.2 por defecto, o seleccionable explícitamente por versión
gopkg.in/yaml.v2 (Go)YAML 1.1
gopkg.in/yaml.v3 (Go)YAML 1.2Significativamente más seguro
Kubernetes / HelmYAML 1.1 (mediante Go yaml.v2)Sí — histórico, muy difícil de migrar
AnsibleYAML 1.1 (mediante PyYAML)

La razón por la que la migración es lenta es la compatibilidad con versiones anteriores. Los sistemas que han dependido de que yes/no se analicen como booleanos durante una década no pueden cambiar silenciosamente ese comportamiento sin romper las configuraciones existentes. Kubernetes en particular es una base instalada masiva donde cambiar la semántica del análisis YAML sería un cambio disruptivo a nivel de clúster.

La conclusión práctica: asume semántica YAML 1.1 en cualquier herramienta que no hayas configurado explícitamente de otro modo. Siempre entrecomilla las cadenas que podrían ser leídas incorrectamente como booleanos, marcas de tiempo o números.

Cómo se ven afectados los sistemas en producción

El código ISO del país Noruega es el ejemplo más citado porque es contraintuitivo — NO parece una abreviatura obvia, no un booleano. Pero el patrón se repite en muchos escenarios del mundo real:

Códigos de aeropuertos IATA. El aeropuerto noruego Harstad/Narvik tiene el código EVE. Seguro. Oslo Gardermoen es OSL. También seguro. Pero cualquier aplicación que use YAML para almacenar códigos de aeropuertos regionales está a un código de ruta no de un booleano false en producción.

Nombres de variables de entorno. ON es un valor perfectamente válido de variable de entorno que significa “habilitado” en algunos sistemas heredados. OFF es su contraparte. Migrar configuraciones de scripts shell a YAML sin entrecomillar estos valores introduce una coerción implícita de tipos silenciosa.

Campos de usuario de correo electrónico. Un usuario cuyo nombre o nombre de usuario sea literalmente n, y o cualquiera de las palabras activadoras se serializará incorrectamente si la aplicación vuelca YAML sin el entrecomillado adecuado. Esto es especialmente insidioso porque solo falla para un subconjunto de usuarios.

Políticas de reinicio de Docker Compose. El valor del campo restart_policy "no" significa “no reiniciar”. Si pierde sus comillas en una conversión de ida y vuelta de YAML, el valor se convierte en false, y Docker Compose puede interpretarlo como “no hay política de reinicio especificada” o lanzar un error de validación — de cualquier manera, el comportamiento de reinicio del contenedor es incorrecto.

Campo shell: de GitHub Actions. Los valores de shell válidos son bash, pwsh, python, sh, cmd, powershell. Ninguno de estos son palabras Norway. Pero alguien que escriba shell: yes o shell: on como marcador durante la edición de un borrador puede sorprenderse cuando YAML lo convierte en un booleano antes de que el validador lo vea.

La solución en todos los casos es la misma: entrecomilla las cadenas que son semánticamente cadenas, independientemente de si un humano las reconocería como palabras clave. Nuestro convertidor de JSON a YAML aplica esto automáticamente — cualquier valor en la lista de palabras Norway se entrecomilla en la salida.

Estrategia de entrecomillado de cadenas

Una vez que entiendes por qué las palabras Norway no coinciden, la solución es elegir la estrategia de entrecomillado correcta para tu caso de uso. YAML admite tres modos, cada uno con diferentes compensaciones.

Auto vs Dobles vs Simples

Entrecomillado Auto (recomendado para la mayoría de las conversiones) deja que la librería decida cuándo son necesarias las comillas. Los valores que serían leídos incorrectamente sin comillas — palabras Norway, números, marcas de tiempo, cadenas que parecen sintaxis YAML — se entrecomillan automáticamente. Todo lo demás permanece como un escalar simple. Esto produce la salida más legible mientras se mantiene seguro.

# Salida en modo Auto
name: Alice          # simple — sin ambigüedad
country: "NO"        # entrecomillado — palabra Norway
age: 30              # simple — número sin ambigüedad
created: "2024-05-04" # entrecomillado — de lo contrario se analizaría como fecha
port: "8080"         # depende de la librería — algunas entrecomillan cadenas que parecen números

Cadenas con comillas dobles envuelven todos los valores de cadena entre comillas dobles. Esto es explícito y auditable — cualquier lector puede ver que todos estos valores son cadenas sin razonar sobre la especificación. La compensación es la verbosidad y la legibilidad humana reducida, especialmente para configuraciones profundamente anidadas.

# Modo de comillas dobles
name: "Alice"
country: "NO"
replicas: "3"         # incluso los números se convierten en cadenas — puede causar errores de esquema

Ten cuidado: si tu esquema de destino espera un número y lo serializas como una cadena entrecomillada, el parser YAML lo tipará correctamente como una cadena, pero Kubernetes u otro consumidor estricto puede rechazar el campo por ser del tipo incorrecto.

Las cadenas con comillas simples son una característica exclusiva de YAML — JSON no tiene sintaxis de comilla simple. Las comillas simples son literales: no hay secuencias de escape dentro de ellas. El único caso especial es que una comilla simple dentro de una cadena entre comillas simples debe duplicarse (''). Las comillas simples son ideales para cadenas que contienen barras invertidas o caracteres especiales que necesitarían escapado en comillas dobles.

# Modo de comillas simples
pattern: 'C:\Users\alice\Documents'  # no se necesita escape
regex: '\d+\.\d+'                    # las barras invertidas son literales

Para conversiones de JSON a YAML destinadas a volver en forma de JSON, prefiere el modo Auto o Doble. Las cadenas entre comillas simples introducen una sintaxis específica de YAML que requiere un parser con conocimiento de YAML en el camino de vuelta.

Escalares en bloque (| y >)

La sintaxis de escalar en bloque de YAML es genuinamente útil para cadenas multilínea — algo que JSON maneja de forma incómoda con secuencias de escape \n.

El escalar de bloque literal | preserva los saltos de línea exactamente:

# Bloque literal — los saltos de línea se conservan
script: |
  #!/bin/bash
  set -euo pipefail
  echo "Starting deployment"
  kubectl apply -f manifest.yaml

# Representación JSON equivalente (ilegible)
# {"script": "#!/bin/bash\nset -euo pipefail\necho \"Starting deployment\"\nkubectl apply -f manifest.yaml\n"}

El escalar de bloque plegado > une las líneas con espacios, convirtiendo cada salto de línea en un espacio (excepto las líneas en blanco, que se convierten en saltos de línea):

# Bloque plegado — los saltos de línea se convierten en espacios
description: >
  This service handles authentication
  for the entire platform. It supports
  OAuth2, SAML, and API key authentication.

# Resultado: "This service handles authentication for the entire platform. It supports OAuth2, SAML, and API key authentication.\n"

Los escalares en bloque son ideales para incrustar certificados TLS, scripts shell multilínea o consultas SQL en configuraciones YAML — escenarios donde el equivalente JSON sería una larga línea escapada que ningún humano puede leer.

Al convertir de JSON a YAML, la mayoría de los conversores (incluido el nuestro) usan el modo Auto y representan las cadenas multilínea con escalares en bloque solo cuando detectan saltos de línea incrustados. Las cadenas de una sola línea obtienen escalares de flujo (entrecomillados o simples). Usa nuestro convertidor de JSON a YAML para ver la salida antes de confirmarla en un manifiesto.

Sangría — 2 vs 4 espacios, tabulaciones prohibidas

Las reglas de sangría de YAML son más estrictas de lo que parecen. La especificación tiene una regla absoluta y una convención que varía según el ecosistema.

La regla absoluta: las tabulaciones están prohibidas. Cada nivel de sangría debe usar espacios. Un carácter de tabulación en un archivo YAML es un error de análisis en la mayoría de los parsers:

# INCORRECTO — las tabulaciones causan errores de análisis
apiVersion: apps/v1
kind: Deployment
metadata:
	name: my-app     # ← carácter de tabulación aquí → ParseError

# CORRECTO — solo espacios
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app      # ← dos espacios

El mensaje de error que verás varía según la librería. En PyYAML de Python:

yaml.scanner.ScannerError: while scanning for the next token
found character '\t' that cannot start any token

En yaml.v3 de Go:

yaml: line 4: found character that cannot start any token

Configura tu editor para expandir las tabulaciones en espacios para los archivos YAML. En VS Code, añade a la configuración de tu espacio de trabajo: "[yaml]": { "editor.insertSpaces": true, "editor.tabSize": 2 }.

La convención: 2 vs 4 espacios. Ambas son válidas. Las convenciones del ecosistema difieren:

EcosistemaConvenciónRazón
Manifiestos de Kubernetes2 espaciosLa documentación y los ejemplos oficiales usan 2
Charts de Helm2 espaciosSigue la convención de K8s
Docker Compose2 espaciosEjemplos de la especificación oficial de Compose
GitHub Actions2 espaciosEjemplos de workflows oficiales
Playbooks de Ansible2 espaciosDocumentación oficial
Configuraciones tradicionales4 espaciosCoincide con el valor predeterminado de embellecimiento de JSON

Para cualquier archivo que vaya a ser consumido por Kubernetes o Docker Compose, usa 2 espacios. Para archivos de configuración independientes que solo serán leídos por humanos y herramientas personalizadas, cualquiera funciona — solo sé consistente dentro de un archivo. Nuestro convertidor de JSON a YAML usa por defecto sangría de 2 espacios y te permite cambiar a 4 para los proyectos que lo prefieran.

Una regla más: los elementos hijo deben sangrarse más que su padre, pero el número de espacios adicionales puede ser cualquier entero positivo (1, 2, 3, 4…) — siempre que sea consistente dentro de un bloque. En la práctica, usa siempre 2 o 4 para la legibilidad.

Manejo de números en JSON ↔ YAML

Ambos formatos admiten números, pero los casos extremos difieren lo suficiente como para causar errores en producción.

Pérdida de precisión para números grandes

El tipo Number de JavaScript es un float IEEE 754 de 64 bits. Puede representar enteros exactamente hasta 2^53 − 1 = 9.007.199.254.740.991. Más allá de eso, se pierde la precisión de los enteros:

// Pérdida de precisión de JavaScript — esto no es un problema de YAML, pero afecta al análisis de JSON
JSON.parse('{"v": 9007199254740993}').v
// → 9007199254740992   (el 3 se convirtió en 2 — un bit perdido)

// Seguro — dentro del rango 2^53
JSON.parse('{"v": 9007199254740991}').v
// → 9007199254740991   (exacto)

Esto importa para la conversión de JSON a YAML en entornos JavaScript porque la precisión ya se pierde antes de que comience la serialización YAML. metadata.resourceVersion de Kubernetes es un campo de cadena específicamente porque las versiones de recursos pueden superar el rango seguro de enteros. Otros campos que parecen números pequeños — observedGeneration, componentes de uid — son más seguros, pero cualquier campo int64 en una respuesta de K8s está potencialmente afectado.

Soluciones alternativas:

  • Usa Python o Go para los pipelines de conversión que involucren números grandes — ambos manejan enteros arbitrarios de forma nativa.
  • En Node.js, usa un parser JSON que admita BigInt: JSON.parse(text, (_, v) => typeof v === 'number' && !Number.isSafeInteger(v) ? BigInt(v) : v).
  • Para los campos que deben convertirse sin pérdida, serialízalos como cadenas en la fuente.
  • Al revisar YAML convertido, busca campos como resourceVersion, generation y valores derivados de marcas de tiempo.

Peculiaridades de octal y hexadecimal

YAML 1.1 trata ciertas cadenas que parecen números como enteros no decimales:

# Sorpresas del análisis YAML 1.1
permissions: 0755   # se analiza como octal 493, no decimal 755
value: 0x1A         # se analiza como hexadecimal 26, no la cadena "0x1A"

# Comportamiento de YAML 1.2
permissions: 0755   # se mantiene como el entero 755 (decimal) — el octal requiere el prefijo 0o
permissions: 0o755  # se analiza como octal 493 tanto en 1.1 como en 1.2

# Seguro para ambas especificaciones — entrecomilla cualquier valor con cero inicial
permissions: "0755"  # siempre la cadena "0755"

La trampa del octal es particularmente peligrosa para los permisos de archivo de Unix, los componentes de dirección IP con ceros iniciales (algunos dispositivos de red) y cualquier código numérico que use ceros iniciales para el relleno (códigos postales, códigos de producto). Siempre entrecomilla estos valores al escribir YAML a mano, o asegúrate de que tu conversor los entrecomille — nuestro convertidor de JSON a YAML detecta las cadenas numéricas de JSON y preserva su tipo de cadena.

Conversiones del mundo real

El problema Norway y las estrategias de entrecomillado se vuelven concretos cuando los aplicas a escenarios de conversión reales.

Manifiesto de Kubernetes desde JSON

El flujo de trabajo canónico: kubectl get deploy my-app -o json te da el objeto en vivo como JSON. Quieres limpiarlo (eliminar status, creationTimestamp, campos administrados) y confirmarlo en git como manifiesto YAML.

JSON fuente (abreviado):

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "my-app",
    "namespace": "production",
    "labels": {
      "app": "my-app",
      "region": "NO"
    }
  },
  "spec": {
    "replicas": 3,
    "selector": {
      "matchLabels": { "app": "my-app" }
    },
    "template": {
      "spec": {
        "containers": [{
          "name": "app",
          "image": "registry.example.com/my-app:v1.2.3",
          "env": [
            { "name": "REGION", "value": "NO" },
            { "name": "ENABLE_FEATURE", "value": "yes" }
          ]
        }]
      }
    }
  }
}

Salida YAML esperada (con protección Norway):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
  labels:
    app: my-app
    region: "NO"          # entrecomillado — palabra Norway
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    spec:
      containers:
        - name: app
          image: registry.example.com/my-app:v1.2.3
          env:
            - name: REGION
              value: "NO"           # entrecomillado — palabra Norway
            - name: ENABLE_FEATURE
              value: "yes"          # entrecomillado — palabra Norway

Fíjate que replicas: 3 se deja sin entrecomillar — es un entero legítimo que Kubernetes espera como número. Las palabras Norway en los valores de labels y env están entrecomilladas. Un conversor ingenuo que no gestione los booleanos YAML 1.1 produciría silenciosamente region: false y value: false.

Después de convertir, valida con: kubectl apply --dry-run=client -f manifest.yaml. Esto detecta errores de esquema sin tocar el clúster.

Prueba la conversión en nuestro convertidor de JSON a YAML — pega el JSON de arriba y ve la salida segura para Norway al instante. Usa nuestro convertidor de YAML a JSON para verificar la conversión de vuelta.

Docker Compose desde JSON

Los pipelines de CI/CD a veces generan configuraciones de Docker Compose programáticamente desde un almacén de configuración JSON, luego las escriben en disco como YAML para que los desarrolladores las lean.

Trampa crítica — política de reinicio:

{"restart_policy": "no"}

En Compose, restart_policy: "no" es un valor válido que significa “nunca reiniciar el contenedor”. Sin comillas en YAML, esto se convierte en restart_policy: false, lo que Docker Compose puede tratar como la misma semántica (falso = sin reinicio) o rechazar con un error de validación de tipo — el comportamiento varía según la versión de Compose. El entrecomillado es obligatorio.

También observa: deploy.restart_policy.condition: "on-failure" de Compose v3 — el valor on-failure contiene la palabra on, pero está con guión y no está en la lista de activadores, así que en realidad es seguro. Sin embargo, condition: on (sin el -failure) no coincidiría. Entrecomilla los valores de las variables de entorno en el bloque environment: si podrían ser palabras Norway.

Valida los archivos de Compose después de la conversión: docker-compose config analiza y vuelve a mostrar la forma canónica, exponiendo los errores de tipo.

Workflow de GitHub Actions

Los workflows de GitHub Actions son archivos YAML editados a mano por los desarrolladores. El escenario de conversión más común es leer datos de workflow de la API de GitHub (que devuelve JSON) y convertirlos a un archivo YAML local para editar.

Los campos clave a vigilar:

# SEGURO — no hay palabras Norway en GitHub Actions estándar
on:                        # "on" es una clave YAML aquí, no un valor — se gestiona de forma diferente
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: |
          npm install
          npm test
        env:
          NODE_ENV: production   # seguro — no es una palabra Norway
          DEBUG: "off"           # palabra Norway en valor — necesita entrecomillado

Nota: on: como clave YAML es especial — el problema Norway se aplica a los valores, no a las claves. Pero on como valor (como DEBUG: on) activaría la coerción. El bloque env: merece especial atención porque los valores de las variables de entorno son cadenas, pero muchos de ellos son indicadores cortos que podrían colisionar con las palabras Norway.

Para los workflows que incluyen especificaciones de shell:, los valores válidos (bash, pwsh, sh, python) son todos seguros frente a la coerción Norway. Los valores personalizados deben entrecomillarse de forma proactiva.

Plan JSON de Terraform → YAML

terraform show -json tfplan > plan.json produce una representación JSON detallada de lo que Terraform planea crear, modificar o destruir. Convertir esto a YAML lo hace más legible para las revisiones de pull request y las auditorías de cumplimiento.

terraform plan -out=tfplan
terraform show -json tfplan > plan.json
# Luego convierte con nuestra herramienta o una librería

El JSON del plan de Terraform es complejo y profundo. Preocupaciones clave al convertir:

  1. IDs de enteros grandes. Los IDs de recursos de nube (IDs de cuentas de AWS, números de proyecto de GCP) y los valores de atributos computados pueden ser números grandes. Convierte mediante Python o Go para evitar la pérdida de precisión de float64.

  2. Cadenas de restricción de versión. Terraform usa ~>, >=, <= en las restricciones de versión del proveedor. Estos son valores de cadena que YAML maneja correctamente siempre que no sean palabras Norway — pero ~> es seguro.

  3. Valores de configuración del proveedor. Las salidas del plan de Terraform pueden incluir valores de configuración para los recursos. Si un campo booleano por defecto es false y se representa como "no" en algún esquema de proveedor, ese es un riesgo Norway al volver a YAML.

  4. El bloque .sensitive_values. Los valores sensibles se redactan como booleanos true en el plan JSON. Estos sobreviven la conversión limpiamente ya que true no es una palabra Norway en ninguna versión de YAML.

La conversión de Terraform a YAML es principalmente para la revisión humana, no para volver a alimentar en Terraform. No uses manifiestos YAML como entrada de Terraform — el formato nativo de Terraform es HCL, y su formato de entrada JSON es específico y está documentado por separado.

Ejemplos de código — 4 lenguajes

Node.js (eemeli/yaml + js-yaml)

El ecosistema de Node.js tiene dos librerías YAML dominantes con manejo del problema Norway significativamente diferente:

// eemeli/yaml — recomendada, YAML 1.2 por defecto, segura para Norway
import { stringify } from 'yaml';
import { readFileSync } from 'fs';

const jsonInput = readFileSync('input.json', 'utf8');
const data = JSON.parse(jsonInput);

// Por defecto: YAML 1.2 — "NO" se mantiene como "NO", sin coerción booleana
const yamlOutput = stringify(data);
console.log(yamlOutput);
// region: NO      ← seguro en 1.2, pero para máxima compatibilidad entrecomíllalo explícitamente

// Forzar comportamiento YAML 1.1 (para entornos K8s/Helm que analizan 1.1)
const yamlForK8s = stringify(data, { version: '1.1' });
// region: 'NO'    ← entrecomillado automático porque 1.1 analizaría NO como false
console.log(yamlForK8s);
// js-yaml — extendido, pero con semántica YAML 1.1, arriesgado para Norway sin cuidado
import yaml from 'js-yaml';
import { readFileSync } from 'fs';

const data = JSON.parse(readFileSync('input.json', 'utf8'));

// Volcado predeterminado — las palabras Norway pueden no estar entrecomilladas
const unsafe = yaml.dump(data);
// region: NO    ← ¡se analizará como false si lo lee un parser 1.1!

// Más seguro: usa un esquema personalizado o fuerza el entrecomillado
const safer = yaml.dump(data, {
  schema: yaml.JSON_SCHEMA,   // restringe a tipos compatibles con JSON
  noCompatMode: false,
  lineWidth: -1,
  quotingType: '"',
  forceQuotes: false,         // solo entrecomilla cuando sea necesario según el esquema JSON
});

Para nuevos proyectos, prefiere eemeli/yaml. Su valor predeterminado de YAML 1.2 es más seguro, su API Document proporciona control detallado sobre el entrecomillado y gestiona mejor la fidelidad de conversión de ida y vuelta. Para proyectos que ya usan js-yaml, usa la opción JSON_SCHEMA para restringirlo a tipos seguros para JSON. Para un análisis más profundo del filtrado y transformación de JSON antes de la conversión, consulta la hoja de referencia de jq en la línea de comandos para patrones de preprocesamiento.

Python (PyYAML + ruamel.yaml)

Python es el lenguaje dominante para las herramientas de Kubernetes, Ansible y los pipelines de ingeniería de datos — todos usuarios intensivos de YAML.

import json
import yaml
import sys

# PyYAML — simple, estándar, pero YAML 1.1 por defecto
with open('input.json') as f:
    data = json.load(f)

output = yaml.dump(data, default_flow_style=False, allow_unicode=True)
# country: 'NO'   ← PyYAML es lo suficientemente inteligente como para entrecomillar automáticamente las palabras Norway
# Pero NO entrecomilla "yes", "no" (en minúsculas) en todas las configuraciones:
# enabled: 'yes'   ← entrecomillado
# tag: y           ← puede o no estar entrecomillado dependiendo de la versión

print(output)
import json
import sys
from ruamel.yaml import YAML

# ruamel.yaml — fidelidad de conversión de ida y vuelta, admite YAML 1.2, recomendado para producción
yaml_rt = YAML()
yaml_rt.default_flow_style = False
yaml_rt.width = 4096              # evita el ajuste de línea no deseado
yaml_rt.best_map_flow_style = False

with open('input.json') as f:
    data = json.load(f)

yaml_rt.dump(data, sys.stdout)
# Preserva el orden de las claves, maneja las palabras Norway correctamente, admite anclas en la conversión de ida y vuelta

Para los scripts de automatización de Ansible y Kubernetes donde conviertes respuestas JSON de la API a manifiestos YAML, ruamel.yaml es la opción más segura. PyYAML es adecuado para scripts simples donde controlas los datos de entrada y has verificado que no aparecen palabras Norway.

Si usas archivos de configuración JSON5 o JSONC (con comentarios) antes de la conversión, elimina las extensiones primero — consulta la guía de formato de JSON5 y JSONC para parsers compatibles.

Go (gopkg.in/yaml.v3)

Go es el lenguaje del propio ecosistema de Kubernetes — kubectl, Helm, Argo, Flux y la mayoría de los operadores de K8s están escritos en Go.

package main

import (
    "encoding/json"
    "fmt"
    "os"

    "gopkg.in/yaml.v3"
)

func main() {
    // Leer entrada JSON
    jsonBytes, err := os.ReadFile("input.json")
    if err != nil {
        panic(err)
    }

    // Deserializar JSON en un mapa genérico
    var data map[string]interface{}
    if err := json.Unmarshal(jsonBytes, &data); err != nil {
        panic(err)
    }

    // Serializar a YAML — yaml.v3 usa semántica YAML 1.2
    yamlBytes, err := yaml.Marshal(data)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(yamlBytes))
    // country: "NO"     ← yaml.v3 entrecomilla las palabras Norway correctamente
    // replicas: 3       ← los enteros se mantienen como enteros
    // enabled: true     ← los booleanos se mantienen como booleanos
}

yaml.v3 es una mejora significativa sobre yaml.v2 para la seguridad frente al problema Norway. La librería v2 seguía YAML 1.1 y escribiría NO sin comillas; v3 entrecomilla los valores ambiguos correctamente. Si estás manteniendo un proyecto Go más antiguo que usa v2, actualiza a v3 — la API es en gran medida compatible y la mejora de seguridad vale la migración.

Para la conversión segura de tipos con structs de Go (en lugar de map[string]interface{}), usa etiquetas de struct:

type DeploymentLabels struct {
    App    string `yaml:"app" json:"app"`
    Region string `yaml:"region" json:"region"`
}
// yaml.Marshal en un campo de struct que contiene "NO" lo entrecomillará correctamente en v3

CLI de Bash (yq + jq)

Para scripts de shell y conversiones rápidas ocasionales, yq (la versión de Mike Farah, mikefarah/yq) convierte JSON a YAML en un único comando:

# Instalar yq
brew install yq                         # macOS
sudo wget -qO /usr/local/bin/yq \
  https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
chmod +x /usr/local/bin/yq              # Linux

# Convertir archivo JSON a YAML
yq -P < input.json > output.yaml

# Convertir desde la salida JSON de kubectl
kubectl get deploy my-app -o json | yq -P > manifest.yaml

# Pasar por jq primero para filtrar/transformar, luego convertir a YAML
kubectl get deploy my-app -o json \
  | jq 'del(.status, .metadata.creationTimestamp, .metadata.managedFields)' \
  | yq -P > clean-manifest.yaml

El pipeline jq | yq es un patrón poderoso: usa jq para la manipulación JSON (filtrar campos, remodelar estructuras, consultar valores) y yq -P como el serializador YAML final. Para los patrones de jq, consulta la hoja de referencia de jq en la línea de comandos para 30 patrones del mundo real incluyendo integraciones con kubectl y aws.

Precaución con Norway en yq: yq (mikefarah) respeta el tipo de entrada desde JSON — una cadena JSON "NO" en la entrada se serializará como una cadena YAML con comillas. Pero si generas YAML directamente con yq (no desde entrada JSON), debes entrecomillar explícitamente los valores de palabras Norway. Usa nuestro convertidor de YAML a JSON para validar la conversión de vuelta después de la salida de yq.

Casos extremos y trampas

Más allá del problema Norway, la conversión JSON ↔ YAML tiene varios casos extremos que confunden a los ingenieros experimentados:

  1. YAML con múltiples documentos (separador ---). Un único archivo YAML puede contener múltiples documentos separados por ---. JSON no tiene un concepto equivalente. Al convertir YAML con múltiples documentos a JSON, la mayoría de las herramientas toman solo el primer documento, fusionan todos los documentos en un array o dan error. Al convertir JSON a YAML, se añade un único encabezado de documento --- por convención. Decide y documenta tu comportamiento explícitamente para los pipelines que puedan encontrar archivos con múltiples documentos.

  2. Anclas y alias de YAML. YAML admite definiciones de &ancla y referencias *alias para configuraciones DRY. Al convertir YAML a JSON, las anclas deben expandirse — el JSON resultante puede ser mucho más grande que el YAML fuente. Al convertir JSON a YAML, el conversor no puede reconstruir las anclas que no existían en el original. Los alias son una característica exclusiva de YAML.

  3. Análisis implícito de marcas de tiempo. Los parsers YAML 1.1 convierten 2024-05-04 y 2024-05-04T12:00:00Z a objetos de fecha nativos del lenguaje, no a cadenas. Cuando este objeto de fecha se serializa de vuelta a JSON, la salida depende de la librería: algunos dan salida a cadenas ISO, algunos a marcas de tiempo Unix, algunos a null. Convertir fechas de ida y vuelta a través de YAML sin entrecomillado explícito de cadenas ("2024-05-04") puede cambiar silenciosamente el formato.

  4. La etiqueta !!binary. YAML puede incrustar datos binarios codificados en base64 con la etiqueta !!binary. JSON no tiene tipo binario — el binario debe ser una cadena base64. Al convertir YAML con campos !!binary a JSON, decodifica a cadena base64. Al volver a convertir, no puedes reconstruir la etiqueta binaria sin conocer el esquema. Kubernetes usa !!binary para algunos valores de secreto.

  5. Colisiones de tipo de clave. JSON requiere que las claves de objeto sean cadenas. YAML permite claves de cualquier tipo — claves enteras, claves booleanas, incluso claves de objeto complejas. Un archivo YAML con true: valor o 1: valor como claves no puede representarse fielmente como JSON. La mayoría de los conversores convierten las claves en cadenas, pero la semántica cambia.

  6. Varianza en la representación de null. En YAML, null, ~, Null, NULL y un valor vacío significan todos null. En JSON, solo null es null. Al convertir YAML a JSON, todos estos se normalizan a null. Pero al volver a convertir JSON a YAML, la elección de representación de null importa — ~ es más compacto, null es más explícito. Elige uno y cíñete a él.

  7. Cambios en el orden de clasificación. Los objetos JSON técnicamente no tienen un orden de claves definido (aunque la mayoría de los parsers preservan el orden de inserción). Las asignaciones YAML tampoco tienen un orden requerido. Pero algunas librerías YAML ordenan las claves alfabéticamente por defecto al serializar. Esto puede causar grandes diferencias en el control de versiones si el JSON fuente usó un orden diferente. Configura sort_keys=False en PyYAML (default_flow_style=False solo no previene la ordenación) y opciones equivalentes en otras librerías.

Cuándo NO convertir

La conversión no siempre es la respuesta correcta. Aquí están los escenarios donde es mejor quedarse con el formato original:

No conviertas YAML a JSON si el YAML contiene comentarios que documentan la lógica de negocio. Los comentarios YAML no forman parte del modelo de datos — desaparecen en cualquier serialización a JSON. Si un manifiesto de Kubernetes tiene comentarios que explican por qué se eligió un límite de recurso específico o por qué se hizo una excepción de política de seguridad, convertirlo a JSON destruye esa documentación. Mantén el YAML.

No conviertas automáticamente las configuraciones en los pipelines de CI sin pruebas de conversión de ida y vuelta. Si tu pipeline convierte JSON a YAML y luego aplica el YAML a un clúster, añade un paso de validación de ida y vuelta: YAML de vuelta a JSON, luego compara con el original. Esto detecta las sorpresas de coerción de tipos antes de que lleguen a producción.

No conviertas solo porque una herramienta produce JSON. kubectl, aws, terraform y docker inspect todos producen JSON, pero la mayoría de estas herramientas también aceptan YAML como entrada. Antes de construir un paso de conversión, verifica si la herramienta de destino puede aceptar directamente la entrada YAML — la mayoría de las herramientas modernas de DevOps pueden. Nuestro convertidor de YAML a JSON es más útil cuando específicamente necesitas JSON para una herramienta que no acepta YAML.

No conviertas si los esquemas difieren. Si tu JSON usa claves camelCase y tu consumidor YAML espera snake_case (o viceversa), necesitas un paso de transformación además de una conversión de formato. Una conversión de formato puro producirá YAML sintácticamente correcto pero semánticamente incorrecto. Aborda el mapeo del esquema explícitamente.

No mantengas ambos formatos sincronizados manualmente. Si estás manteniendo un config.json y un config.yaml que se supone que son equivalentes, derivarán. Elige un formato canónico y deriva el otro automáticamente — o mejor, elige un formato y elimina la duplicación.

Preguntas frecuentes

¿El problema Norway de YAML todavía afecta a los sistemas modernos?

Sí — es generalizado en el ecosistema. Kubernetes y Helm usan la librería yaml.v2 de Go (semántica YAML 1.1) en partes significativas de sus bases de código. Ansible usa PyYAML (YAML 1.1). Los workflows de GitHub Actions son analizados por el parser YAML interno de GitHub, que tiene su propio comportamiento. La mayoría de los archivos YAML de CI/CD en uso son procesados por parsers YAML 1.1. Asume semántica 1.1 hasta que hayas verificado lo contrario.

¿Por qué convertiría JSON a YAML si YAML es más difícil de analizar?

La conversión no se trata de la dificultad del parser — se trata de la editabilidad humana. JSON es ideal para las máquinas; YAML es ideal para los humanos que necesitan leer, editar y revisar archivos de configuración. Un manifiesto de Kubernetes confirmado en git, revisado en pull requests y ajustado a mano por ingenieros debería ser YAML. El mismo manifiesto recuperado de la API para el procesamiento programático debería ser JSON. Nuestro convertidor de JSON a YAML une los dos.

¿Puedo convertir JSON ↔ YAML sin pérdida?

Con advertencias, sí — para datos compatibles con JSON. JSON es un subconjunto de YAML 1.2, por lo que cualquier documento JSON válido es YAML 1.2 válido. La conversión JSON → YAML → JSON debería ser sin pérdida para cualquier dato sin coerción implícita de tipos. El problema Norway significa que una cadena JSON "NO" podría sobrevivir el paso de ida solo si el conversor la entrecomilla, y luego sobrevivir el paso de vuelta solo si el parser YAML respeta las comillas. Usa una librería YAML 1.2 para ambas direcciones para garantizar conversiones de ida y vuelta sin pérdida.

¿Cuál es la librería YAML más segura para producción?

Para Python: ruamel.yaml configurada para YAML 1.2. Para Node.js: eemeli/yaml (el paquete yaml en npm). Para Go: gopkg.in/yaml.v3. Las tres implementan la semántica YAML 1.2 o tienen modos YAML 1.2 explícitos y manejan las palabras Norway correctamente. Evita las librerías YAML 1.1 en nuevos proyectos. Si debes usar una librería 1.1 (PyYAML, js-yaml, yaml.v2) por razones de compatibilidad, siempre entrecomilla explícitamente las cadenas propensas al problema Norway.

¿Los manifiestos YAML de Kubernetes admiten comentarios después de la conversión de JSON?

No — los comentarios no pueden recuperarse de JSON. JSON no tiene sintaxis de comentarios, por lo que no hay nada que convertir. Cuando ejecutas kubectl get deploy -o json y conviertes la salida a YAML para almacenamiento en git, el YAML resultante no tendrá comentarios. Los comentarios en un manifiesto de Kubernetes deben ser escritos por un humano después de la conversión. Esta es una razón por la que mantener el YAML escrito a mano como fuente canónica a menudo es preferible a hacer la conversión de ida y vuelta a través de la API JSON.

¿Cómo gestiono los enteros grandes como resourceVersion o las marcas de tiempo en nanosegundos?

metadata.resourceVersion de Kubernetes es un campo de cadena deliberadamente — el equipo de Kubernetes sabía que los parsers JSON en JavaScript y otros tiempos de ejecución basados en float64 perderían precisión en los enteros grandes. Trátalo siempre como una cadena. Para los enteros grandes genuinamente numéricos (como las marcas de tiempo de época en nanosegundos en algunos sistemas de trazado), usa el tipo int de Python, int64 de Go o BigInt de Node.js para el análisis. Nunca los pases por JSON.parse() en JavaScript sin una función revisora personalizada. Al convertir a YAML, estos enteros grandes son seguros — YAML no tiene límite de precisión para los enteros. El peligro está en la conversión de vuelta a través del parser JSON de JavaScript.

¿YAML 1.2 está ampliamente adoptado todavía?

De forma desigual. Las principales librerías de lenguajes han estado migrando: yaml.v3 de Go, ruamel.yaml de Python y eemeli/yaml de Node.js admiten o tienen como valor predeterminado YAML 1.2. Pero Kubernetes, Ansible y gran parte del ecosistema DevOps aún ejecuta parsers YAML 1.1 debido al coste de compatibilidad con versiones anteriores de la migración. La adopción de YAML 1.2 en nuevos proyectos es recomendada, pero asume 1.1 para cualquier sistema que no hayas configurado tú mismo.

¿Debería nuestro equipo estandarizarse en JSON o YAML para las configuraciones?

Estandariza por propósito, no por formato. Usa JSON para las configuraciones consumidas por código (cuerpos de solicitudes de API, archivos de configuración de SDK, herramientas programáticas). Usa YAML para las configuraciones consumidas por humanos (manifiestos de Kubernetes, pipelines de CI, configuraciones de despliegue, playbooks de Ansible). Evita mezclar los dos para la misma configuración — elige una representación por tipo de configuración y automatiza la conversión si necesitas ambas. Cuando necesitas convertir, tanto nuestro convertidor de JSON a YAML como el convertidor de YAML a JSON se ejecutan completamente en tu navegador — ningún dato sale de tu dispositivo.

Pruébalo ahora

¿Listo para convertir un archivo real? Prueba nuestro convertidor de JSON a YAML para transformar JSON en YAML seguro para Kubernetes — entrecomilla automáticamente las palabras Norway (NO, yes, on, off y la lista completa de booleanos YAML 1.1) y te permite elegir sangría de 2 o 4 espacios. Para la dirección inversa, nuestro convertidor de YAML a JSON gestiona anclas, alias y YAML con múltiples documentos. Ambas herramientas se ejecutan completamente en tu navegador — tus datos nunca salen de tu dispositivo, lo que importa cuando trabajas con manifiestos de producción de Kubernetes o planes de Terraform que contienen configuraciones de recursos sensibles.

Artículos relacionados

Ver todos los artículos