sqlpostgresqljsonjsonb

JSONB_OBJECT_KEYS en PostgreSQL: obtener las claves de un objeto JSON como filas

Expande las claves de nivel superior de un objeto JSONB en filas, descubre la forma de tus datos, comprueba que campos existen y reunelos con array_agg.

3 min de lecturaReferencesql · postgresql · json · jsonb · schema

jsonb_object_keys es una funcion que devuelve un conjunto: emite una fila por cada clave de nivel superior de un objeto JSON. Resulta indispensable cuando los datos son semiestructurados y no sabes de antemano que campos hay en una columna. Con ella puedes explorar la forma del JSON, comprobar si los campos esperados estan presentes y construir un inventario de claves de toda una tabla.

Sintaxis y ejemplo basico

La firma es sencilla: jsonb_object_keys(jsonb). Como devuelve un conjunto, produce filas en lugar de un solo escalar. Supon que users ha ganado una columna prefs jsonb con los ajustes del perfil.

SELECT jsonb_object_keys(prefs) AS key
FROM users
WHERE id = 42;

Si prefs es {"theme": "dark", "lang": "en", "newsletter": true}, la consulta devuelve tres filas: theme, lang, newsletter. Algunos comportamientos que conviene conocer:

  • Solo se devuelven las claves de nivel superior. Los objetos anidados no se despliegan.
  • El orden de las claves no esta garantizado; jsonb mantiene su propio orden interno.
  • Para algo que no sea un objeto (array, numero, cadena) obtienes cero filas o un error; pasale solo objetos.
  • Existe la variante json_object_keys para el tipo json; mismo comportamiento, sin normalizacion.

Descubrir la forma de los datos

Cuando una columna jsonb llega de una fuente externa, la primera pregunta es "que claves aparecen aqui". Desplegar las claves de cada fila y agruparlas te da un mapa de campos con sus frecuencias.

SELECT key, COUNT(*) AS rows_with_key
FROM users u,
     jsonb_object_keys(u.prefs) AS key
GROUP BY key
ORDER BY rows_with_key DESC;

Este es el patron canonico: una tabla y una funcion de conjunto en el FROM forman un join LATERAL implicito, de modo que las claves de cada usuario se expanden en filas separadas. El resultado muestra al instante que campos son comunes y cuales son opcionales y raros.

Trampa: si prefs es NULL, la fila de ese usuario simplemente desaparece del resultado, porque la funcion no emite ninguna fila. Para conservar a esos usuarios, usa un LEFT JOIN LATERAL ... ON true explicito, o filtra WHERE prefs IS NOT NULL de forma consciente. De lo contrario tu sondeo se salta en silencio parte de la tabla.

Comprobar que campos opcionales estan presentes

jsonb_object_keys ayuda a encontrar filas que llevan (o no) un campo concreto. Para una sola comprobacion el operador ? es mas comodo, pero recorrer las claves sirve para condiciones dinamicas.

-- users who configured a newsletter preference at all
SELECT id, email
FROM users
WHERE prefs ? 'newsletter';

-- equivalent shape check via the keys set
SELECT id, email
FROM users u
WHERE EXISTS (
    SELECT 1
    FROM jsonb_object_keys(u.prefs) AS key
    WHERE key = 'newsletter'
);

El operador ? (contiene una clave de nivel superior) casi siempre es mas rapido y claro para un campo, sobre todo con un indice GIN en prefs. Recorrer con jsonb_object_keys se justifica cuando la condicion sobre la clave no es trivial, por ejemplo "tiene al menos una clave con prefijo flag_".

Reunir claves con array_agg

A menudo quieres lo contrario de un despliegue: una lista compacta de claves por fila. Combinar array_agg con una subconsulta sobre jsonb_object_keys pliega las claves de vuelta en un array.

SELECT
    u.id,
    u.email,
    (
        SELECT array_agg(key ORDER BY key)
        FROM jsonb_object_keys(u.prefs) AS key
    ) AS configured_keys
FROM users u
WHERE u.prefs IS NOT NULL;

El ORDER BY key dentro de array_agg da un orden estable y legible en lugar del interno de jsonb. Ese array es facil de comparar entre filas: encuentra usuarios con un conjunto de ajustes inusual, o construye un informe de "quien tiene que campos rellenos" sin volcar todo el JSON a la aplicacion.

Otras bases de datos

MySQL no tiene un equivalente directo que devuelva un conjunto: JSON_KEYS(prefs) devuelve un array JSON de claves como un solo valor, no un conjunto de filas. Para desplegarlo recurres a JSON_TABLE. En ClickHouse, el analisis de JSON usa JSONExtractKeys(prefs), que tambien produce un array; expandelo en filas con arrayJoin. Recuerda la regla comun: en los tres sistemas se trata solo de claves de nivel superior, asi que los objetos anidados se analizan en una pasada aparte.

Practica con ejercicios reales

Resuelve ejercicios en el entrenador de SQL con corrección instantánea y pistas.

Abrir el entrenador