0

I have JSON, I want to bypass it and display all the data that is in it. But the problem is that I can't know what data will be there. I made the code, but it only looks for top-level objects. And the rest are not. I will be grateful for your help.

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; 
If you take into account only the top level objects, then this code works

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

And how to deduce the data from the first example, I can not understand. These data must correspond to the hierarchy.

2 Answers 2

1

If you have access to the native JSON types (JSON_ELEMENT_T, JSON_ARRAY_T, etc.) you should always use them over using the APEX_JSON package ans they will have much better performance. A package similar to the one below can be used to output the full hierarchy of a JSON object or array. Feel free to tweak the package to change the format of the output.

Package Specification

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;
/

Package Body

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;
/

Example Call

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;
/

Example Output

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)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the reply, it is very detailed, and I understood, I also made, my version, but it only works with some examples.
0

I also made my own version, but it is limited to 2 levels of objects, and does not take into account arrays.

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; 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.