json - 将 JSON 字符串解析为 Postgres 中的键和值

标签 json postgresql recursive-query jsonb

我正在尝试将 JSON 字符串解析为包含值对的表。

这是 JSON 字符串:

{
"route": {
    "coding": [
        {
            "code": "56",
            "display": "ORAL",
            "userSelected": true
        }
    ]
}
}

我的目标是将其放入这样的表格中:

| parent | key          | value                 | type    |
-------------------------------
| null   | route        | {coding: [...]}       | object  |
| route  | coding       | [{"code": "56", ...}] | array   |
| route  | coding       | {"code": "56", ...}   | object  |
| coding | code         | 56                    | integer |
| coding | display      | ORAL                  | text    |
| coding | userselected | true                  | boolean |

我正在努力进行递归调用。我能够解析数组或对象,只是无法弄清楚如何根据类型调用其中之一。

这是我当前的代码:

WITH RECURSIVE temp (parent, key, value, type) AS (
SELECT parent, key, value, type
FROM t1 
UNION ALL
SELECT parent, key, value, jsonb_typeof(value) AS type
FROM (
SELECT key AS parent, (jsonb_each(value)).*
FROM temp
WHERE temp.type = 'object') AS p1              
), temp2 (parent, key, value, type) AS (
SELECT parent, key, value, type
FROM t1 
UNION ALL
SELECT parent, key, jsonb_array_elements(value), 'object' AS type
FROM temp2
WHERE temp2.type = 'array'
)
SELECT parent, key, value, type FROM temp;

非常感谢任何帮助。谢谢。

最佳答案

In this answer您可以找到一个从 jsonb 对象中提取路径的查询。可以轻松修改它以获得您期望的输出:

with recursive extract_all as
(
    select
        null as parent,
        key, 
        value,
        jsonb_typeof(value) as type
    from my_table
    cross join lateral jsonb_each(jdata)
union all
    select
        key,
        coalesce(obj_key, (arr_key- 1)::text),
        coalesce(obj_value, arr_value),
        jsonb_typeof(coalesce(obj_value, arr_value))
    from extract_all
    left join lateral 
        jsonb_each(case jsonb_typeof(value) when 'object' then value end) 
        as o(obj_key, obj_value) 
        on jsonb_typeof(value) = 'object'
    left join lateral 
        jsonb_array_elements(case jsonb_typeof(value) when 'array' then value end) 
        with ordinality as a(arr_value, arr_key)
        on jsonb_typeof(value) = 'array'
    where obj_key is not null or arr_key is not null
)
select *
from extract_all;

结果:

 parent |     key      |                                value                                |  type   
--------+--------------+---------------------------------------------------------------------+---------
        | route        | {"coding": [{"code": 56, "display": "ORAL", "userSelected": true}]} | object
 route  | coding       | [{"code": 56, "display": "ORAL", "userSelected": true}]             | array
 coding | 0            | {"code": 56, "display": "ORAL", "userSelected": true}               | object
 0      | code         | 56                                                                  | number
 0      | display      | "ORAL"                                                              | string
 0      | userSelected | true                                                                | boolean
(6 rows)    

请注意,数组元素没有键,因此我们应该使用它们的索引来标识它们。从形式上来说,coding 不是嵌套数组元素的父元素。

Working example in rextester.

关于json - 将 JSON 字符串解析为 Postgres 中的键和值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52485363/

相关文章:

php - 使用php将Json数据以json数据类型插入mysql数据库

java - 无法从 JSON 数组检索地理代码

postgresql - 如何在 PostgreSQL 服务器端 C 函数中为数据库 NULL 创建 Datum?

ruby-on-rails - 如何在不使用 EVAL 的情况下将字符串转换为散列

SQL 递归表无限循环

MySQL 在查询中生成注释的子列表

postgresql - 我从哪里获得 libpq 源代码?

sql - 公用表表达式内部的反向聚合

mysql - 如何在 MySQL 中进行递归 SELECT 查询?

json - 使用 jackson 的多个 Any-Setters?