jsonb_array_elements_recursive()

From: "Joel Jacobson" <joel(at)compiler(dot)org>
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: jsonb_array_elements_recursive()
Date: 2021-02-07 09:54:51
Message-ID: 92c4190f-32af-4213-8fb4-f3956059a009@www.fastmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

A particular useful feature of jsonb arrays,
is the ability to represent multidimensional arrays without matching dimensions,
which is not possible with normal PostgreSQL arrays.

SELECT array[[5,2],1,[8,[3,2],6]];
ERROR: multidimensional arrays must have array expressions with matching dimensions

SELECT '[[5,2],1,[8,[3,2],6]]'::jsonb;
[[5, 2], 1, [8, [3, 2], 6]]

When working with jsonb array structures,
there is already jsonb_array_elements() to expand the top-level.

Another case that I think is common is wanting to expand all levels, not just the top-level.

Maybe it's common enough to motivate a new param:

jsonb_array_elements(from_json jsonb [, recursive boolean ])

Or as a separate function. Below is a PoC in PL/pgSQL:

CREATE OR REPLACE FUNCTION jsonb_array_elements_recursive(from_json jsonb, OUT value jsonb)
RETURNS SETOF jsonb
LANGUAGE plpgsql
AS $$
BEGIN
FOR value IN SELECT jsonb_array_elements(from_json) LOOP
IF jsonb_typeof(value) <> 'array' THEN
RETURN NEXT;
ELSE
RETURN QUERY
SELECT * FROM jsonb_array_elements_recursive(value);
END IF;
END LOOP;
END
$$;

# SELECT * FROM jsonb_array_elements_recursive('[[5, 2], 1, [8, [3, 2], 6]]'::jsonb);
value
-------
5
2
1
8
3
2
6
(7 rows)

I tried but failed to implement a PoC in pure SQL,
not even using the new CTE SEARCH functionality,
but maybe it's possible somehow.

/Joel

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Magnus Hagander 2021-02-07 10:21:05 Re: Prevent printing "next step instructions" in initdb and pg_upgrade
Previous Message Tom Lane 2021-02-07 07:55:50 Re: BUG #16583: merge join on tables with different DB collation behind postgres_fdw fails