如何使用pl/pgsql将具有动态元素名称的JSON数据转换为行?

如何使用pl/pgsql将具有动态元素名称的JSON数据转换为行?,json,postgresql,plpgsql,data-conversion,Json,Postgresql,Plpgsql,Data Conversion,我需要从pl/pgsql函数中的restful服务获取json。(我无法控制RESTfulWebService,它是由其他人发布的)。我可以获取json,但无法将其转换为行(用于插入表)。它的简化格式如下。每个GUID都是随机的,我以前不知道它们的内容。当我从文本(使用::json)转换它时,我没有得到任何错误,因此它是有效的json l_json := '{"GUID-0001":{"Id":"1","Field1":"aaa1","Field2":"bbb1"}, "GUID-000

我需要从pl/pgsql函数中的restful服务获取json。(我无法控制RESTfulWebService,它是由其他人发布的)。我可以获取json,但无法将其转换为行(用于插入表)。它的简化格式如下。每个GUID都是随机的,我以前不知道它们的内容。当我从文本(使用::json)转换它时,我没有得到任何错误,因此它是有效的json

    l_json := '{"GUID-0001":{"Id":"1","Field1":"aaa1","Field2":"bbb1"}, "GUID-0002":{"Id":"2","Field1":"aaa2","Field2":"bbb2"}}'::json;
我尝试了几个Postgresql json函数,但每次都出现不同的错误。i、 当我使用json_array_elements()函数时,我得到了“错误:无法在非数组上调用json_array_elements”。当我尝试json_each_text()函数时,我得到了“错误:查询没有结果数据的目标”

我需要一个结果集,如下所示:

GUID     | Id | Field1 | Field2
---------+----+--------+-------
GUID-0001| 1  |   aaa1 |   bbb1
GUID-0002| 1  |   aaa2 |   bbb2

我认为解决这个问题的最简单方法是在插入之前稍微调整json,然后使用它将json转换为行

将外部对象转换为应用程序代码中的数组,并将
GUID-000x
值移动到相关对象中
GUID
键下,如下所示:

[
  {
    "GUID": "GUID-0001",
    "Id": "1",
    ...
  },
  {
    "GUID": "GUID-0002",
    "Id": "1",
    ...
  }
  ...
]
我不知道你的应用程序代码使用的是什么语言,但我假设你可以使用某种形式的
reduce
来完成这项工作

一旦数据格式正确,就可以使用
json\u populate\u记录集
如下所示:

insert into your_table
    select GUID, Id, Field1, Field2
  from json_populate_recordset(null::your_table, _your_modified_json_from_above)
;

json\u populate\u记录集
基本上接受json并将键与
中定义的列相匹配,并相应地添加值。关键是,您的对象键必须与列名完全匹配,并且您的值需要与这些列上定义的数据类型匹配(或能够转换为匹配)。

您可以使用
jsonb\u object\u keys()
获取所有键,并使用该键访问JSON中的字段:

with data(doc) as (
  values ('{"GUID-0001":{"Id":"1","Field1":"aaa1","Field2":"bbb1"}, "GUID-0002":{"Id":"2","Field1":"aaa2","Field2":"bbb2"}}'::jsonb)
)
select t.uid, 
       d.doc -> t.uid ->> 'Id' as id,
       d.doc -> t.uid ->> 'Field1' as column1,
       d.doc -> t.uid ->> 'Field2' as column2
from data d, jsonb_object_keys(doc) as t(uid);
返回:

uid       | id | column1 | column2
----------+----+---------+--------
GUID-0001 | 1  | aaa1    | bbb1   
GUID-0002 | 2  | aaa2    | bbb2   
您可以将其放入接受jsonb作为参数的函数中:

create or replace function store_json(p_doc jsonb)
  returns void
as
$$
  insert into the_table (guid, id, column1, column2)
  select t.uid, 
         (d.doc -> t.uid ->> 'Id')::int,
         d.doc -> t.uid ->> 'Field1',
         d.doc -> t.uid ->> 'Field2'
  from (select p_doc) as d(doc), 
       jsonb_object_keys(doc) as t(uid);
$$
language sql;

您是否正在尝试将插入的
文件“转换为行”?另外,您有一个嵌套对象,因此您无法仅使用一个pg json函数获得所需的结果集。我愿意使用每一个json函数来实现这个目标,但我还是不明白,因为我对postgresql和json都是新手。-这可能会给你一个方向。但是,如果你真的不熟悉postgresql和json,在我看来你会有更多的问题。你至少需要学习一些基础知识。@Abelisto你的评论是最接近的解决方案。因为我还没有什么名声,所以我不能对你的评论投赞成票。非常感谢。我无法控制restful web服务。这是第三方web服务。(我还将这一信息添加到我的问题中)。因此,我只能在下载json后处理它。如果有办法改变json内容,我会这么做,这样你就不会有调用此服务的应用程序代码了?我正在使用postgresql扩展来获取json。这部分工作得很好。如果有办法的话,我只想能够使用pl/pgsql将这个json数据转换成带行的SELECT语句。我仍然不能投票,但这解决了我的问题。非常感谢。