2022-03-24

Print JSON attributes names and types

Script to traverse and print types (except one with null values) and change values to attribute names (useful for testing purposes)

DECLARE
   l_clob CLOB;
   l_json json_object_t;

   l_number NUMBER := 1;   
   
   FUNCTION process_object(p_json json_object_t, p_level NUMBER := 0, p_parent_object_name VARCHAR2 := NULL) RETURN json_object_t IS
      l_keys  JSON_KEY_LIST;
      l_padding VARCHAR2(100):= LPAD(' ', p_level * 3, ' ');
      
      l_result json_object_t := p_json;
   BEGIN
      l_keys := p_json.get_keys;
      
      FOR i IN 1 .. l_keys.count LOOP
         IF p_json.get(l_keys(i)).is_object THEN
            dbms_output.put_line(l_padding || l_keys(i) || ' is object');
            l_result.put(
               l_keys(i), 
               process_object(TREAT(p_json.get(l_keys(i)) AS json_object_t), p_level + 1, LTRIM(p_parent_object_name || '.' || l_keys(i), '.'))
               );
         ELSIF p_json.get(l_keys(i)).is_number THEN
            dbms_output.put_line(l_padding || l_keys(i) || ' is number');
            l_result.put(l_keys(i), l_number);
            l_number := l_number + 1;
            --             
         ELSIF p_json.get(l_keys(i)).is_string THEN
            dbms_output.put_line(l_padding || l_keys(i) || ' is string');
            l_result.put(l_keys(i), LTRIM(p_parent_object_name || '_', '_') || l_keys(i));
         ELSIF p_json.get(l_keys(i)).is_array THEN
            dbms_output.put_line(l_padding || l_keys(i) || ' is array');

            DECLARE
              l_arr JSON_ARRAY_T := TREAT(p_json.get(l_keys(i)) AS JSON_ARRAY_T);
              l_new_array JSON_ARRAY_T := NEW JSON_ARRAY_T;
            BEGIN  
              FOR j IN 0 .. l_arr.get_size - 1 LOOP
                IF l_arr.get(j).is_object THEN
                  l_new_array.append(
                     process_object(TREAT(l_arr.get(j) AS json_object_t), p_level + 1, LTRIM(p_parent_object_name || '.' || l_keys(i) || '[' || j || ']', '.'))
                     );
                END IF;
                -- check other types?
              END LOOP;
              l_result.put(l_keys(i), l_new_array);
            END;
         ELSE 
            dbms_output.put_line(l_padding || l_keys(i) || ' is unknown');
            l_result.put(l_keys(i), LTRIM(p_parent_object_name || '_', '_') || l_keys(i));
         END IF;
      END LOOP;
      
      RETURN l_result;
   END;
BEGIN
   l_json := json_object_t.parse(l_clob);
   dbms_output.put_line( process_object(l_json).stringify );
END;
/