flatten_json.sql
text/plain
create or replace function flatten(p_input jsonb, p_path text)
returns table(path text, key text, value text)
as
$$
begin
if jsonb_typeof(p_input) = 'array' then
return query
select f.*
from jsonb_array_elements(p_input) as a(element)
cross join flatten(a.element, p_path) f;
else
return query
select p_path, e.key, e.value #>> '{}'
from jsonb_each(p_input) as e(key, value)
where jsonb_typeof(e.value) not in ('object', 'array')
or (jsonb_typeof(e.value) = 'array' and jsonb_typeof(e.value -> 0) <> 'object')
union all
select f.*
from jsonb_each(p_input) as t(key,value)
cross join flatten(t.value, p_path||'/'||t.key) as f
where jsonb_typeof(t.value) = 'object'
union all
select f.*
from jsonb_each(p_input) as t(key,value)
cross join jsonb_array_elements(t.value) as a(element)
cross join flatten(a.element, p_path||'/'||t.key) as f
where jsonb_typeof(t.value) = 'array'
and jsonb_typeof(t.value -> 0) = 'object';
end if;
end;
$$
language plpgsql
immutable
parallel safe
;
create or replace function flatten(p_input jsonb)
returns table(path text, key text, value text)
as
$$
select *
from flatten(p_input, '');
$$
language sql
immutable
parallel safe
;