(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo extraer y transformar columnas JSON en Python para datos

João Barros 30 de October de 2026 5 min de lectura

Extraer y transformar columnas que contienen JSON es una tarea habitual cuando se trabaja con APIs, logs o volcado de datos que mezclan texto y estructura. Saber cómo normalizar campos anidados en un DataFrame pandas ahorra tiempo y permite análisis y modelado más fiables. Además, cuando los JSON están embebidos como cadenas en una columna, es importante sistematizar estos pasos para garantizar reproducibilidad y rendimiento, sobre todo cuando se procesan miles a millones de registros.

Requisitos previos

  • Python 3.8+ instalado
  • pandas y json instalados (pip install pandas)
  • Noociones básicas de DataFrame y diccionarios Python

Paso 1: Identificar la columna JSON y el formato

Primero es importante ver cómo están almacenados los JSON: cadenas JSON, diccionarios ya convertidos o listas anidadas. Abra algunas filas y verifique tipos y ejemplos extremos (filas con valores nulos o JSON inválido). Para conjuntos mayores, muestree 100–1 000 filas para entender la variabilidad. Decidir la estrategia correcta (json.loads, ast.literal_eval o dejar como dict) depende del formato: si la columna es del tipo object con strings, hay que deserializar; si ya es dict, puede ir directamente a la normalización.

import pandas as pd
import json

# Exemplo de DataFrame com coluna JSON como string
df = pd.DataFrame({
    'id': [1, 2, 3],
    'payload': [
        '{"user": {"name": "Ana", "age": 30}, "tags": ["a","b"]}',
        '{"user": {"name": "Bruno", "age": 25}, "tags": ["b"]}',
        '{"user": {"name": "Carla", "age": null}, "tags": []}'
    ]
})

# Verificar primeiras linhas
print(df.head())

Paso 2: Convertir cadenas JSON en diccionarios

Si la columna es texto, conviértala a dict con json.loads. Maneje errores comunes: valores nulos, JSON inválido o encoding inesperado (por ejemplo, comillas simples). Para producción, cree una función robusta que registre fallos y devuelva None en caso de error. En escenarios grandes (10k+ filas), procese en bloques para reducir memoria y registrar la tasa de éxito de la deserialización (p. ej.: 99% válidos, 1% inválidos).

def safe_load(s):
    if pd.isna(s):
        return None
    try:
        return json.loads(s)
    except Exception:
        # Pode registar a linha problemática aqui
        return None

# Aplicar a conversão
df['payload_json'] = df['payload'].apply(safe_load)
print(df['payload_json'])

Paso 3: Normalizar campos anidados con pandas.json_normalize

pandas.json_normalize es ideal para expandir diccionarios en columnas planas. Para estructuras con listas de objetos puede usar record_path y meta para controlar la expansión. Para conjuntos de datos medianos (p. ej. 50k registros) la normalización directa crea un DataFrame con columnas como user.name y user.age; verifique los tipos y renombre columnas según sea necesario. Si se espera una media de 3 tags por registro, explotar (explode) multiplicará el número de filas — planifique memoria e índices.

from pandas import json_normalize

# Normalizar a coluna de dicionários
normalized = json_normalize(df['payload_json'])
# Se o resultado tiver colunas como 'user.name', renomear ou juntar ao original
print(normalized)

# Juntar ao DataFrame original
df2 = pd.concat([df.drop(columns=['payload_json']), normalized], axis=1)
print(df2)

Paso 4: Manejar listas y campos opcionales

Las listas (ej.: tags) pueden convertirse a una cadena separada por comas, contarse o explotarse en varias filas. Elija según el análisis: si necesita métricas por usuario, cuente; si necesita análisis de frecuencia, explote. Los campos ausentes (None) deben recibir valores por defecto o tipos coherentes para evitar problemas en agregaciones (por ejemplo, rellenar age nulo con la media o con un sentinel como -1). Para columnas numéricas, convierta explícitamente con astype o pd.to_numeric con errors='coerce'.

# Converter lista em string e criar contagem
df2['tags_str'] = df2['tags'].apply(lambda x: ','.join(x) if isinstance(x, list) else '')
df2['tags_count'] = df2['tags'].apply(lambda x: len(x) if isinstance(x, list) else 0)

# Tratar age nulo: preencher com média ou valor sentinel
df2['user.age'] = df2['user.age'].fillna(df2['user.age'].mean())
print(df2[['id','user.name','user.age','tags_str','tags_count']])

Paso 5: Explotar listas en varias filas (cuando sea necesario)

Si necesita una fila por tag, use explode. Esto es útil para análisis de frecuencia, mapas o joins posteriores con tablas de referencia. Atención: explotar transforma listas vacías en NaN; rellene o filtre según sea necesario. Ejemplos prácticos: 3 registros con media 2 tags → tras explode tendrá ~6 filas; en producción, estime el factor de multiplicación para prever el tamaño final.

# Explodir para uma linha por tag
exploded = df2.explode('tags')
# Se existirem entradas vazias, cuidado com NaN
exploded['tags'] = exploded['tags'].fillna('')
print(exploded[['id','user.name','tags']])

Verificar el resultado

Confirme que las columnas esperadas existen, los tipos son correctos y los recuentos concuerdan con el original. Haga comprobaciones simples: comparar la suma de tags_count con el número total de tags antes de explotar, verificar el porcentaje de valores nulos por columna y visualizar muestras de filas problemáticas. En pipelines, escriba tests unitarios que validen esas invariantes (p. ej.: total_tags antes == total_tags después).

# Verificações rápidas
print(df2.info())
print(df2[['id','user.name','user.age']].head())

# Conferir soma das tags_count com número total de tags antes de explodir
print('total tags (contagem):', df2['tags_count'].sum())
print('total tags (explodidas):', exploded['tags'].shape[0])

Conclusión

Extraer y transformar columnas JSON en Python con pandas permite pasar de datos semiestructurados a tablas listas para análisis o modelado. Para producción, integre este proceso en un ETL, valide esquemas con jsonschema, registre errores de parsing y utilice procesamiento por bloques cuando se trate con grandes volúmenes. Consejo práctico: mantenga siempre un paso de validación y algunos ejemplos de filas reales (10–20 filas representativas) para evitar sorpresas en los datos.