CodeGym /Cursos /SQL SELF /Juntando e modificando objetos JSON com o operador || e a...

Juntando e modificando objetos JSON com o operador || e a função jsonb_concat()

SQL SELF
Nível 34 , Lição 0
Disponível

Se JSONB é tipo um baú mágico onde a gente joga os dados, então || e jsonb_concat() são as ferramentas pra juntar esses baús ou mexer no que tem dentro deles. Na vida real, pode rolar de precisar juntar vários objetos JSON, adicionar dados de um em outro ou unir arrays numa lista só.

Por exemplo, imagina que tu tem dois objetos JSONB:

{"name": "Alice", "age": 25}

e

{"city": "Wonderland", "hobbies": ["reading", "chess"]}

Tu quer chegar nisso aqui:

{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}

Ou juntar dois arrays JSONB:

[1, 2, 3]

e

[4, 5, 6]

pra que o resultado fique assim:

[1, 2, 3, 4, 5, 6]

Tudo isso rola usando || ou jsonb_concat(). Bora ver como funciona.

Operador || pra juntar JSONB

O operador || deixa tu juntar dois objetos ou arrays JSONB no PostgreSQL. É simples, rápido e fácil de usar. Olha as regras principais:

  • Se tu junta dois objetos JSONB, o resultado vai ter as chaves e valores dos dois.
  • Se as chaves batem, o valor do operando da direita substitui o da esquerda.
  • Se tu junta arrays JSONB, os elementos dos dois arrays viram um array só.

Exemplo 1: Juntando dois objetos JSONB

SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"city": "Wonderland", "hobbies": ["reading", "chess"]}'::jsonb AS merged_object;

Resultado:

{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}

Exemplo 2: Atualizando valores quando as chaves são iguais

SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"age": 30, "city": "Wonderland"}'::jsonb AS updated_object;

Resultado:

{"name": "Alice", "age": 30, "city": "Wonderland"}

Repara que o valor da chave "age" do objeto da direita substituiu o da esquerda.

Exemplo 3: Juntando arrays

SELECT '[1, 2, 3]'::jsonb || '[4, 5, 6]'::jsonb AS merged_array;

Resultado:

[1, 2, 3, 4, 5, 6]

Função jsonb_concat() pra juntar JSONB

A função jsonb_concat() faz basicamente o mesmo que o operador ||, mas é mais flexível se tu precisa usar ela em funções, triggers ou consultas dinâmicas. Ela recebe dois argumentos do tipo JSONB e devolve o resultado juntado.

Exemplo: usando jsonb_concat()

SELECT jsonb_concat('{"a": 1, "b": 2}'::jsonb, '{"b": 3, "c": 4}'::jsonb) AS combined;

Resultado:

{"a": 1, "b": 3, "c": 4}

Juntando objetos e arrays: detalhes e pegadinhas

Quando tu junta objetos com chaves iguais, lembra que os valores do objeto da direita têm prioridade.

Tipo assim:

SELECT '{"key1": "value1"}'::jsonb || '{"key1": "value2"}'::jsonb AS result;

Resultado:

{"key1": "value2"}

Se tu não quiser que um valor substitua o outro, guarda esses dados em chaves diferentes ou usa outro esquema (tipo array).

Agora, arrays sempre são juntados adicionando os elementos do array da direita no da esquerda. Por exemplo:

SELECT '["a", "b"]'::jsonb || '["c", "d"]'::jsonb AS result;

Resultado:

["a", "b", "c", "d"]

Se dentro do array tem objetos, a ordem dos objetos é mantida:

SELECT '[{"id": 1}, {"id": 2}]'::jsonb || '[{"id": 3}]'::jsonb AS result;

Resultado:

[{"id": 1}, {"id": 2}, {"id": 3}]

Exemplos práticos

Atualizando o perfil do usuário. Imagina que a gente tem uma tabela users, onde os perfis ficam em JSONB:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    profile JSONB
);

INSERT INTO users (profile) VALUES ('{"name": "Alice", "age": 25}');

Agora queremos adicionar a cidade onde mora:

UPDATE users 
SET profile = profile || '{"city": "Wonderland"}'
WHERE id = 1;

Resultado da consulta:

{"name": "Alice", "age": 25, "city": "Wonderland"}

Juntando dados de pedidos. Digamos que temos uma tabela orders:

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    details JSONB
);

INSERT INTO orders (details) VALUES ('{"items": [{"product": "laptop", "quantity": 1}]}');

Agora vamos adicionar mais um produto no pedido:

UPDATE orders
SET details = jsonb_set(
    details,
    '{items}',
    details->'items' || '[{"product": "mouse", "quantity": 2}]'::jsonb
)
WHERE id = 1;

Resultado da consulta:

{"items": [{"product": "laptop", "quantity": 1}, {"product": "mouse", "quantity": 2}]}

Diferenças entre || e jsonb_concat()

Na prática, o operador || e a função jsonb_concat() fazem a mesma coisa. Usa || pra consultas simples, porque é mais curto de escrever. A função jsonb_concat() é massa quando tu precisa chamar ela dentro de código ou trigger.

Erros comuns e como evitar

Erro: tentar juntar tipos incompatíveis.

SELECT '{"key": "value"}'::jsonb || '["value"]'::jsonb;

Resultado:

ERROR:  cannot concatenate jsonb objects and arrays

Aqui à esquerda tem um objeto e à direita um array — o PostgreSQL não consegue juntar assim. Pra funcionar, os dois lados têm que ser do mesmo tipo: ou dois objetos, ou dois arrays.

Vacilo: não criar índices quando trabalha com JSONB

Se tu filtra muito por valores dentro de campos JSONB e não tem índice — as consultas vão ficar bem lentas. Não é erro clássico, mas o desempenho vai pro saco. Não esquece de usar índices GIN:

CREATE INDEX idx_profile_data ON employees USING gin(profile);
2
Tarefa
SQL SELF, nível 34, lição 0
Bloqueado
Atualizando um objeto JSONB considerando a substituição de chaves
Atualizando um objeto JSONB considerando a substituição de chaves
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION