使用PL/SQL绕过JSON对象,在Oracle中以key-value格式输出所有数据

Bypass the JSON object using PL / SQL, and output all data in key value format in Oracle

我有 JSON,我想绕过它并显示其中的所有数据。但问题是我不知道那里会有什么数据。我编写了代码,但它只查找顶级对象。而其余的则不是。我会很感激你的帮助。

DECLARE 
   l_object     json_object_t; 
   l_key_list   json_key_list; 
   v_clob            CLOB; 
   tv                apex_json.t_values;
BEGIN 
   -- JSON_OBJECT can figure out what keys it has... 
  v_clob := '{"devices":{"id":"d652f632-0835-871b-a140-58701f019000","scale_id":"88348A32BD3D149FE055000000000001"},"data":{"external_id":"40023"},"data_weight":{"weight":"20322","prevWeight":"1000","prevTransaction":"1607680754361","transaction":"1607680754361","on":"false","transactionDataCount":"1","stable":"false","duration":"12","transactionMaxWeight":"2000","perimetr":"true","driverInCar":"false"}}';
  apex_json.parse(tv,v_clob); 


  l_object := json_object_t.parse (v_clob); 

   l_key_list := l_object.get_keys; 
 
   FOR counter IN 1 .. l_key_list.COUNT 
   LOOP 
      DBMS_OUTPUT.put_line ( 
            l_key_list (counter) 
         || ' : ' 
         || apex_json.get_varchar2(p_path => l_key_list (counter), p_values => tv)); 
   END LOOP; 
END; 
如果您只考虑顶级对象,则此代码有效

DECLARE 
   l_object     json_object_t; 
   l_key_list   json_key_list; 
   v_clob            CLOB; 
   tv                apex_json.t_values;
BEGIN 
   -- JSON_OBJECT can figure out what keys it has... 
  v_clob := '{"devices":"3423","data":"okwwwe"}';
  apex_json.parse(tv,v_clob); 


  l_object := json_object_t.parse (v_clob); 


 
       
 

   l_key_list := l_object.get_keys; 
 
   FOR counter IN 1 .. l_key_list.COUNT 
   LOOP 
      DBMS_OUTPUT.put_line ( 
            l_key_list (counter) 
         || ' : ' 
         || apex_json.get_varchar2(p_path => l_key_list (counter), p_values => tv)); 
   END LOOP; 
END; 

RESULT :
devices : 3423
data : okwwwe

以及如何从第一个示例中推导出数据,我无法理解。这些数据必须对应层级。

如果您可以访问本机 JSON 类型(JSON_ELEMENT_TJSON_ARRAY_T 等),您应该始终使用它们而不是使用 APEX_JSON 包和它们会有更好的表现。类似于下面的包可用于输出 JSON 对象或数组的完整层次结构。随意调整包以更改输出格式。

包装规格

CREATE OR REPLACE PACKAGE output_json
AS
    c_padding_char     CONSTANT VARCHAR2 (1) := '-';
    c_padding_amount   CONSTANT PLS_INTEGER := 1;

    PROCEDURE output_scalar (p_element    json_element_t,
                             p_padding    PLS_INTEGER,
                             p_json_key   VARCHAR2 DEFAULT NULL);

    PROCEDURE output_object (p_object json_object_t, p_padding PLS_INTEGER);

    PROCEDURE output_array (p_array json_array_t, p_padding PLS_INTEGER);

    PROCEDURE output_element (p_element    json_element_t,
                              p_padding    PLS_INTEGER,
                              p_json_key   VARCHAR2 DEFAULT NULL);
END;
/

包体

CREATE OR REPLACE PACKAGE BODY output_json
AS
    PROCEDURE output_scalar (p_element    json_element_t,
                             p_padding    PLS_INTEGER,
                             p_json_key   VARCHAR2 DEFAULT NULL)
    IS
    BEGIN
        DBMS_OUTPUT.put_line (
               LPAD (c_padding_char, p_padding, c_padding_char)
            || CASE WHEN p_json_key IS NOT NULL THEN p_json_key || ' : ' END
            || CASE
                   WHEN p_element.is_boolean
                   THEN
                       CASE WHEN p_element.to_boolean THEN 'TRUE' ELSE 'FALSE' END || ' (boolean)'
                   WHEN p_element.is_date
                   THEN
                       TO_CHAR (p_element.TO_DATE, 'YYYY-MM-DD') || ' (date)'
                   WHEN p_element.is_number
                   THEN
                       p_element.TO_NUMBER || ' (number)'
                   WHEN p_element.is_string
                   THEN
                       p_element.TO_STRING || ' (string)'
               END);
    END;

    PROCEDURE output_object (p_object json_object_t, p_padding PLS_INTEGER)
    IS
        l_keys      json_key_list;
        l_element   json_element_t;
    BEGIN
        l_keys := p_object.get_keys;

        FOR i IN 1 .. l_keys.COUNT
        LOOP
            l_element := p_object.get (l_keys (i));
            output_element (l_element, p_padding, l_keys (i));
        END LOOP;
    END;

    PROCEDURE output_array (p_array json_array_t, p_padding PLS_INTEGER)
    IS
    BEGIN
        FOR i IN 0 .. p_array.get_size - 1
        LOOP
            output_element (p_array.get (i), p_padding);
        END LOOP;
    END;

    PROCEDURE output_element (p_element    json_element_t,
                              p_padding    PLS_INTEGER,
                              p_json_key   VARCHAR2 DEFAULT NULL)
    IS
    BEGIN
        DBMS_OUTPUT.put_line (
            CASE
                WHEN p_json_key IS NOT NULL AND NOT p_element.is_scalar THEN p_json_key || ' : '
            END);

        IF p_element.is_scalar
        THEN
            output_scalar (p_element, p_padding, p_json_key);
        ELSIF p_element.is_object
        THEN
            output_object (TREAT (p_element AS json_object_t), p_padding + c_padding_amount);
        ELSIF p_element.is_array
        THEN
            output_array (TREAT (p_element AS json_array_t), p_padding + c_padding_amount);
        END IF;
    END;
END;
/

调用示例[​​=19=]
DECLARE
    l_clob   CLOB;
BEGIN
    l_clob :=
        '{"arr":[1,2,3],"devices":{"id":"d652f632-0835-871b-a140-58701f019000","scale_id":"88348A32BD3D149FE055000000000001"},"data":{"external_id":"40023"},"data_weight":{"weight":"20322","prevWeight":"1000","prevTransaction":"1607680754361","transaction":"1607680754361","on":"false","transactionDataCount":"1","stable":"false","duration":"12","transactionMaxWeight":"2000","perimetr":"true","driverInCar":"false"}}';

    output_json.output_element (json_element_t.parse (l_clob), 0);
END;
/

示例输出

arr :
--1 (number)
--2 (number)
--3 (number)
devices :
--id : "d652f632-0835-871b-a140-58701f019000" (string)
--scale_id : "88348A32BD3D149FE055000000000001" (string)
data :
--external_id : "40023" (string)
data_weight :
--weight : "20322" (string)
--prevWeight : "1000" (string)
--prevTransaction : "1607680754361" (string)
--transaction : "1607680754361" (string)
--on : "false" (string)
--transactionDataCount : "1" (string)
--stable : "false" (string)
--duration : "12" (string)
--transactionMaxWeight : "2000" (string)
--perimetr : "true" (string)
--driverInCar : "false" (string)

我也做了自己的版本,但是仅限于2层对象,没有考虑数组。

DECLARE 
   l_object     json_object_t; 
   l_key_obj    json_key_list;
   v_clob       CLOB; 
   tv           apex_json.t_values;
   obj_in_obj   JSON_OBJECT_T;
   l_key_list   json_key_list; 

BEGIN 
 
v_clob := '{
"devices":{
"id":"d652f632-0835-871b-a140-58701f019000",
"scale_id":"88348A32BD3D149FE055000000000001"
},
"data":{
"external_id":"40023"
},
"data_weight":{
"weight":"20322",
"prevWeight":"1000",
"prevTransaction":"1607680754361",
"transaction":"1607680754361",
"on":"false",
"transactionDataCount":"1",
"stable":"false",
"duration":"12",
"transactionMaxWeight":"2000",
"perimetr":"true",
"driverInCar":"false"
}
}';

  apex_json.parse(tv,v_clob); 

  l_object := json_object_t.parse (v_clob);
  l_key_list := l_object.get_keys; 

   FOR counter IN 1 .. l_key_list.COUNT 
   LOOP 

   obj_in_obj :=  l_object.get_object(l_key_list (counter));
   l_key_obj := obj_in_obj.get_keys;
       FOR counter_all_obj IN 1 .. l_key_obj.COUNT 
   LOOP 
      DBMS_OUTPUT.put_line ( 
         l_key_list (counter)||'.'||l_key_obj (counter_all_obj) 
         || ' : ' 
         || apex_json.get_varchar2(p_path => l_key_list (counter)||'.'|| l_key_obj (counter_all_obj), p_values => tv)); 
   END LOOP;

   END LOOP;

END;