I'm trying to parse a nested JSON in Postgres, which has the following structure:
{
"id": 0,
"children": [{
"id": 965,
"children": [{
"id": 967
},
{
"id": 969
},
{
"id": 971
},
{
"id": 973
}
]
},
{
"id": 974,
"children": [{
"id": 976
},
{
"id": 978
}
]
}
]
}
My desired output form is this:
-------------------------------------------
|parent_id |child_id |
-------------------------------------------
|0 |965 |
|0 |974 |
|965 |967 |
|965 |969 |
|965 |971 |
|965 |973 |
|974 |976 |
|974 |978 |
-------------------------------------------
I am trying to use RECURSIVE CTEs to do so, however, with whatever I've tried, I run into either could not identify an equality operator for type json or ERROR: set-returning functions are not allowed in CASE. I'm able to get the data for one level, but that's far from what I intend to do, so any suggestions as to what I could do differently would be of great help.
Here is a how you can quickly try it out if needed, along with all what've I've tried and the errors those raised. Also it'd be a bonus if your suggestions work for json and jsonb both.
Thanks
Edit: The number of levels of the JSON isn't fixed, it could be upto any level (max 3-4).
Edit: Adding queries I tried here itself:
with recursive cte(id,json_element) as (
select tree->'id',tree->'children' from json_test
union
select json_element->'id',json_element->'children' from cte
) select * from cte;
--could not identify an equality operator for type json
WITH RECURSIVE cte(id, children) AS (
SELECT
tree->'id' as id,
tree->'children' as children
FROM json_test
UNION ALL
SELECT
children -> 'id',
children -> 'children'
FROM cte,
--json_each(CASE WHEN json_typeof(cte.children) <> 'object' THEN '{}' :: JSON ELSE cte.children END) AS t
json_each(CASE WHEN json_typeof(cte.children) = 'array' THEN json_array_elements(cte.children) ELSE cte.children END) AS t
)
SELECT * FROM cte WHERE json_typeof(cte.children) <> 'object';
--ERROR: set-returning functions are not allowed in CASE
--Hint: You might be able to move the set-returning function into a LATERAL FROM item.
I also tried multiple changes to these queries but ended up with the same errors in the end.
->>instead of->ERROR: operator does not exist: text ->> unknowntree->'id'works thentree->>'id'will work as well.tree->'id'andtree->>'id'work, giving the same result, but not in the desired form. Whereas, if I also addtree->>'children'andjson_element -> 'children', I get the theERROR: operator does not exist: text ->> unknownerror.