问题描述
我正在尝试将PL / SQL包中定义的记录类型转换为JSON。
我发现在SQL中,我可以使用select json_object(*) from SomeTable
返回具有表中每一列属性的对象,但是对于PL / SQL代码中的记录类型,我似乎无法做到这一点。
示例程序包,其中包含类型和根据类型返回(序列化)json的函数:
create or replace package Customer as
type RT_Address is record (
Line1 varchar2(100),Line2 varchar2(100),City varchar2(100)
);
type RT_Customer is record (
FirstName varchar2(100),LastName varchar2(100),Address RT_Address
);
function AsJson(P_Customer RT_Customer)
return varchar2;
end;
create or replace package body devvanessa.Customer as
function AsJson(P_Customer RT_Customer)
return varchar2 is
V_DOM jdom_t;
V_JSON json_object_t;
V_JSONBody varchar2(4000);
begin
V_JSON := json_object(P_Customer); -- PLS-00103: Encountered the symbol when expecting one of the following: . ( * @ % & - + / at mod remainder rem <een exponent (**)> || multiset value
if V_DOM.append(P_CUSTOMER) then -- PLS-00306: wrong number or types of arguments
null;
end if;
V_JSONBody := V_Json.STRINGIFY;
return V_JSONBody;
end;
end;
上面的内容略有简化,因为我实际上想存储此json并对其进行其他操作,但这确实显示了我的问题的核心:
如何在PL / SQL中将记录类型转换为Json,而无需分别指定所有单个字段。 我也很好奇它会如何工作。
我一直在搜索各种资源,例如documentation on JSON functions,Oracle 19's JSON documentation,以及我在json_object_t
和jdom_t
类型上获得的代码完成提示,但到目前为止我完全找不到任何证据。
这将起作用:
V_JSon.Put('FirstName',P_Customer.FirstName);
-- repeated for each property
通过这种方式获取json,但需要我分别指定每个字段。
解决方法
JSON_OBJECT_T没有采用记录类型的构造函数,因此您将需要显式定义每个键/值以定义JSON。您尝试执行的操作不需要JDOM_T。以下是有关如何将记录类型转换为JSON并返回的示例。
DECLARE
TYPE RT_Address IS RECORD
(
Line1 VARCHAR2 (100),Line2 VARCHAR2 (100),City VARCHAR2 (100)
);
TYPE RT_Customer IS RECORD
(
FirstName VARCHAR2 (100),LastName VARCHAR2 (100),Address RT_Address
);
l_customer1 rt_customer
:= rt_customer ('John','Doe',rt_address ('123 Main Street','Apartment# 2A','London'));
l_customer2 rt_customer
:= rt_customer ('Jane','Smith',rt_address ('456 Broken Dreams Blvd',NULL,'Greenville'));
l_json json_object_t;
l_record rt_customer;
FUNCTION customer_record_to_json (P_Customer RT_Customer)
RETURN json_object_t
IS
l_address json_object_t := json_object_t ();
l_customer json_object_t := json_object_t ();
BEGIN
l_address.put ('Line1',p_customer.address.line1);
l_address.put ('Line2',p_customer.address.line2);
l_address.put ('City',p_customer.address.city);
l_customer.put ('FirstName',p_customer.firstname);
l_customer.put ('LastName',p_customer.lastname);
l_customer.put ('Address',l_address);
RETURN l_customer;
END;
FUNCTION customer_json_to_record (p_customer_json json_object_t)
RETURN rt_customer
IS
l_address_json json_object_t := json_object_t ();
l_address rt_address;
l_customer rt_customer;
BEGIN
l_address_json := p_customer_json.get_object ('Address');
l_address.line1 := l_address_json.get_string ('Line1');
l_address.line2 := l_address_json.get_string ('Line2');
l_address.city := l_address_json.get_string ('City');
l_customer.firstname := p_customer_json.get_string ('FirstName');
l_customer.lastname := p_customer_json.get_string ('LastName');
l_customer.address := l_address;
RETURN l_customer;
END;
BEGIN
l_json := customer_record_to_json (l_customer1);
DBMS_OUTPUT.put_line ('Customer 1 (JSON): ' || l_json.stringify);
l_record := customer_json_to_record (l_json);
DBMS_OUTPUT.put_line ('Customer 1 (Record) (FirstName): ' || l_record.firstname);
DBMS_OUTPUT.put_line ('Customer 1 (Record) (LastName): ' || l_record.lastname);
DBMS_OUTPUT.put_line ('Customer 1 (Record) (Line1): ' || l_record.address.line1);
DBMS_OUTPUT.put_line ('Customer 1 (Record) (Line2): ' || l_record.address.line2);
DBMS_OUTPUT.put_line ('Customer 1 (Record) (City): ' || l_record.address.city);
l_json := customer_record_to_json (l_customer2);
DBMS_OUTPUT.put_line ('Customer 2 (JSON): ' || l_json.stringify);
l_record := customer_json_to_record (l_json);
DBMS_OUTPUT.put_line ('Customer 2 (Record) (FirstName): ' || l_record.firstname);
DBMS_OUTPUT.put_line ('Customer 2 (Record) (LastName): ' || l_record.lastname);
DBMS_OUTPUT.put_line ('Customer 2 (Record) (Line1): ' || l_record.address.line1);
DBMS_OUTPUT.put_line ('Customer 2 (Record) (Line2): ' || l_record.address.line2);
DBMS_OUTPUT.put_line ('Customer 2 (Record) (City): ' || l_record.address.city);
END;
更新
仅可以JSON_OBJECT(*)
创建一个JSON对象,但是*扩展不适用于记录类型,因为您将获得一个ORA-40579: star expansion is not allowed
。
如果您确实希望使用JSON_OBJECT
来创建JSON而不是JSON_OBJECT_T,则需要预定义所使用的类型(不在pl / sql块中),并且仍然需要定义每个字段在JSON结构中。您还需要定义一个RT_CUSTOMER类型的表类型,以便您可以从中查询。
CREATE TYPE RT_Address AS OBJECT (Line1 VARCHAR2 (100),Line2 VARCHAR2 (100),City VARCHAR2 (100));
CREATE TYPE RT_Customer AS OBJECT
(
FirstName VARCHAR2 (100),LastName VARCHAR2 (100),Address RT_Address
);
CREATE TYPE rt_customer_t AS TABLE OF rt_customer;
SELECT json_object (
'firstname' VALUE firstname,'lastname' VALUE lastname,'address' VALUE
json_object ('line1' VALUE TREAT (address AS rt_address).line1,'line2' VALUE TREAT (address AS rt_address).line2,'city' VALUE TREAT (address AS rt_address).city)) as customer
FROM TABLE (
rt_customer_t (
RT_Customer ('John','London')),RT_Customer ('Jane','Greenville'))));