jsonb_build_array() and json_build_array()
Purpose: Create a JSON array from a variadic list of array values of arbitrary SQL data type.
Signature For the jsonb
variant:
input value: VARIADIC "any"
return value: jsonb
Notes: Each function in this pair takes an arbitrary number of actual arguments of mixed SQL data types. The data type of each argument must have a direct JSON equivalent or allow implicit conversion to such an equivalent.
Use this ysqlsh
script to create the required type "t" and then to execute the ASSERT
.
create type t as (a int, b text);
do $body$
declare
v_17 constant int := 17;
v_dog constant text := 'dog';
v_true constant boolean := true;
v_t constant t := (17::int, 'cat'::text);
j constant jsonb := jsonb_build_array(v_17, v_dog, v_true, v_t);
expected_j constant jsonb := '[17, "dog", true, {"a": 17, "b": "cat"}]';
begin
assert
j = expected_j,
'unexpected';
end;
$body$;
Using jsonb_build_array()
is straightforward when you know the structure of your target JSON value statically, and just discover the values dynamically. However, it doesn't accommodate the case that you discover the desired structure dynamically.
The following ysqlsh
script shows a feasible general workaround for this use case. The helper function "f()" generates the variadic argument list as the text representation of a comma-separated list of SQL literals of various data types. Then it invokes jsonb_build_array()
dynamically. Obviously this brings a performance cost. But you might not have an alternative.
create function f(variadic_array_elements in text) returns jsonb
language plpgsql
as $body$
declare
stmt text := '
select jsonb_build_array('||variadic_array_elements||')';
j jsonb;
begin
execute stmt into j;
return j;
end;
$body$;
-- Relies on "type t as (a int, b text)" created above.
do $body$
declare
v_17 constant int := 17;
v_dog constant text := 'dog';
v_true constant boolean := true;
v_t constant t := (17::int, 'cat'::text);
expected_j constant jsonb := jsonb_build_array(v_17, v_dog, v_true, v_t);
j constant jsonb := f(
$$
17::integer,
'dog'::text,
true::boolean,
(17::int, 'cat'::text)::t
$$
);
begin
assert
j = expected_j,
'unexpected';
end;
$body$;