jsonb_object_agg()
This page documents the preview version (v2.23). Preview includes features under active development and is for development and testing only. For production, use the stable version (v2024.1). To learn more, see Versioning.
Purpose: This is an aggregate function. (Aggregate functions compute a single result from a SETOF
input values.) It creates a JSON object whose values are the JSON representations of the aggregated SQL values. It is most useful when these to-be-aggregated values are "row" type values with two fields. The first represents the key and the second represents the value of the intended JSON object's key-value pair.
Signature:
input value: anyelement
return value: jsonb
Notes: The syntax "order by... nulls first" within the parentheses of the aggregate function (a generic feature of aggregate functions) isn't useful here because the order of the key-value pairs of a JSON object has no semantic significance.
JSON objects and their keys.
A JSON object is a set of key-value pairs where each key is (taken to be) unique and the order is undefined and insignificant. (See also the accounts of the jsonb_set()
and jsonb_insert()
functions.)
This means that if a key-value pair is specified more than once, in any context that defines an object value, then the one that is most recently specified wins. Here's a simple example:
select ('{"f2": 42, "f7": 7, "f2": null}'::jsonb)::text;
This is the result:
{"f2": null, "f7": 7}
(In the other direction, the ::text
typecast of a jsonb
object uses the convention of ordering the pairs alphabetically by the key.)
Try this demonstration of the jsonb_object_agg()
function:
do $body$
declare
object_agg jsonb not null := '"?"';
expected_object_agg constant jsonb not null :=
'{"f1": 1, "f2": 2, "f3": null, "f4": 4}'::jsonb;
begin
with tab as (
values
('f4'::text, 4::int),
('f1'::text, 1::int),
('f3'::text, null::int),
('f2'::text, 2::int))
select
jsonb_object_agg(column1, column2)
into strict object_agg
from tab;
assert (object_agg = expected_object_agg), 'unexpected';
end;
$body$;
It finishes silently, showing that the assert
holds.
Now try this counter-example. The DO
block specifies both the value for key "f2" and the value for key "f7" twice:
do $body$
declare
object_agg jsonb not null := '"?"';
expected_object_agg constant jsonb not null :=
'{"f2": null, "f7": 7}'::jsonb;
begin
with tab as (
values
('f2'::text, 4::int),
('f7'::text, 7::int),
('f2'::text, 1::int),
('f2'::text, null::int))
select
jsonb_object_agg(column1, column2)
into strict object_agg
from tab;
assert (object_agg = expected_object_agg), 'unexpected';
end;
$body$;
It, too, finishes silently, showing that, again, the assert
holds.