Ambas as suas respostas vinculadas contêm soluções, mas pode ser bom ter uma resposta abrangente.
Postgres é fortemente tipado. Suas funções e operadores retornam tipos específicos.
->
retorna jsonb. Compare-o não com SQL null, mas com jsonb null
. test=# select '{"i_am_null": null, "a_string": "null"}'::jsonb->'i_am_null' = 'null'::jsonb;
?column?
----------
t
(1 row)
test=# select '{"i_am_null": null, "a_string": "null"}'::jsonb->'a_string' = 'null'::jsonb;
?column?
----------
f
(1 row)
->>
retorna texto e converte jsonb null em SQL null
. test=# select '{"i_am_null": null, "a_string": "null"}'::jsonb->>'i_am_null' is null;
?column?
----------
t
(1 row)
test=# select '{"i_am_null": null, "a_string": "null"}'::jsonb->>'a_string' is null;
?column?
----------
f
(1 row)
Observe que enquanto jsonb null é apenas outro valor, SQL null é muito especial. Nulo não é um valor, é a falta de um valor. Nulo é igual a nada, nem mesmo nulo . Pode parecer que converter null para jsonb deve produzir jsonb null, mas o padrão SQL exige que null converta apenas para null caso contrário, isso significaria que null é equivalente a algo.
É por isso que jsonb null pode ser convertido em null, mas null não é convertido em jsonb null.
null::jsonb
é nulo . Isso é inconveniente, mas exigido pelo padrão SQL. É uma das razões pelas quais a conversão entre jsonb e texto não é recomendada.