Saltar al contenido
jsonbeautifiers
Español

Aplanar JSON

Convierte JSON anidado en rutas de clave de un solo nivel, y vuelve atrás.

Anidado
Plano

Nada de lo que pegues sale de tu navegador. La lista de permitidos de connect-src convierte eso en una garantía del navegador, no en una promesa. Compruébalo tú mismo

Aplanar convierte un documento anidado en un único nivel de rutas con puntos: {"a":{"b":1}} pasa a ser {"a.b":1}. Desaplanar lo devuelve a su forma original.

Es lo que haces antes de cargar JSON en cualquier cosa rectangular: una hoja de cálculo, un data frame, un almacén de feature flags, un archivo de entorno, un formulario.

El ida y vuelta, y el único caso que lo rompe

Aplanar y luego desaplanar devuelve el documento original, incluidos los objetos y arrays vacíos, que varias implementaciones descartan sin decir nada.

Hay exactamente un caso en el que no puede: una clave que contiene el propio separador. Dado {"a.b": 1}, la ruta aplanada "a.b" es indistinguible de un {"a":{"b":1}} anidado. Esta herramienta lo detecta y te avisa en lugar de producir algo que no volverá. Cuando ocurra, elige otro separador.

Arrays: notación de índice o notación de corchetes

La notación con puntos da tags.0 y tags.1. La de corchetes da tags[0] y tags[1]. Ambas hacen el ida y vuelta aquí, y el parser de entrada acepta cualquiera de las dos.

La notación con puntos es la que produce json_normalize de pandas y la que espera la mayoría de pipelines de CSV. La de corchetes se lee mejor cuando una clave podría ser numérica, porque tags[0] y tags.0 son ambiguos de una forma en que tags["0"] no lo es.

Dónde aplanar pierde información

Una clave de objeto numérica se vuelve indistinguible de un índice de array una vez aplanada. {"2024": {"total": 1}} se aplana a "2024.total", y desaplanarlo con la detección de arrays activada produce un array con 2024 huecos vacíos.

Desactiva «claves numéricas como arrays» cuando tus claves sean de verdad cadenas numéricas, algo habitual en cualquier cosa indexada por año, por código de estado HTTP o por ID.

How to do this in code

Aplanar en código.

py Python, pandas

record_path es el argumento que convierte una relación de uno a muchos en filas en vez de en columnas numeradas.

import pandas as pd

# The workhorse. sep defaults to '.'
df = pd.json_normalize(records)

# Explode a nested array into one row per element
df = pd.json_normalize(
    records,
    record_path='items',
    meta=['id', 'created_at'],
)
sh jq
# Every leaf as a dotted path
jq -r 'paths(scalars) as $p | "\($p | join(".")) = \(getpath($p))"' in.json

# A flat object rather than lines
jq '[leaf_paths as $p | {(($p | map(tostring) | join("."))): getpath($p)}] | add' in.json
js JavaScript

La rama de los contenedores vacíos es la línea que la mayoría de implementaciones se dejan, y es la razón por la que no hacen el ida y vuelta.

function flatten(value, prefix = '', out = {}) {
  if (value && typeof value === 'object') {
    const entries = Array.isArray(value)
      ? value.map((v, i) => [i, v])
      : Object.entries(value);
    if (entries.length === 0) {
      out[prefix] = value;      // preserve {} and []
      return out;
    }
    for (const [k, v] of entries) {
      flatten(v, prefix ? `${prefix}.${k}` : String(k), out);
    }
    return out;
  }
  out[prefix] = value;
  return out;
}

Preguntas frecuentes

¿Qué separador debería usar?
Un punto, salvo que tus claves contengan puntos. El guion bajo es la segunda opción habitual, y la barra resulta útil cuando el resultado va a parar a algo que ya piensa en términos de rutas.
¿Puedo aplanar solo una parte del documento?
Fija un límite de profundidad. Todo lo que quede más allá se deja como valor anidado, que es justo lo que quieres cuando la parte profunda es un bloque opaco que almacenas en vez de consultar.
¿Qué pasa con null?
Se conserva por defecto, como una clave plana con valor null. Hay una opción para omitir los nulls, útil para un diff y peligrosa para un ida y vuelta.