Serializing/marshalling 包级用户将记录类型定义为 JSON
Serializing/marshalling package level user define record types to JSON
我正在尝试将 PL/SQL 包中定义的记录类型转换为 JSON。
我发现在 SQL 中,我可以使用 select json_object(*) from SomeTable
到 return 对象,这些对象在 table 中的每一列都有一个 属性,但我似乎无法使用 PL/SQL 代码中的记录类型来执行此操作。
具有类型和函数的示例包 return(序列化)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 没有接受记录类型的构造函数,因此您需要显式定义每个 keys/values 来定义 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 类型的 table 类型,以便您可以从中查询。
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',
'Doe',
rt_address ('123 Main Street', 'Apartment# 2A', 'London')),
RT_Customer ('Jane',
'Smith',
rt_address ('456 Broken Dreams Blvd', NULL, 'Greenville'))));
我正在尝试将 PL/SQL 包中定义的记录类型转换为 JSON。
我发现在 SQL 中,我可以使用 select json_object(*) from SomeTable
到 return 对象,这些对象在 table 中的每一列都有一个 属性,但我似乎无法使用 PL/SQL 代码中的记录类型来执行此操作。
具有类型和函数的示例包 return(序列化)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 没有接受记录类型的构造函数,因此您需要显式定义每个 keys/values 来定义 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 类型的 table 类型,以便您可以从中查询。
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',
'Doe',
rt_address ('123 Main Street', 'Apartment# 2A', 'London')),
RT_Customer ('Jane',
'Smith',
rt_address ('456 Broken Dreams Blvd', NULL, 'Greenville'))));