Reputation: 15
I have a simple JSON object { "A" : {"key1":"value1", "key2":"value2", "key3":"value3"} } that I want to turn into rows with a single column "Key". The problem is that I don't know ahead of time what the name of the key is, or how many there are. In other words there could be "key4", "key5", . . . And there could also be "xyz1":"XYZ1" as a key/value in the "A" object. I can iterate through this JSON object with JavaScript but my task here is, assuming that the is a JSON object stored in an Oracle database as a CLOB, how do I turn all of the keys into a table? Or is it possible. I looked at possibly using JSON_TABLE but I have to specify the schema and a json path to each column which I cannot specify ahead of time. If this was an array and each elements schema is fixed, it seems that JSON_TABLE is built for that. But I don't have such a JSON object. Only one like described earlier. Ideas?
Upvotes: 1
Views: 1948
Reputation: 6084
I don't believe there is a SQL function to get the names of the keys similar to the JSON_OBJECT_T.GET_KEYS
function in PL/SQL. One option is to use a pipelined table function to parse the JSON and you can get the parent key, child keys, and value of the child keys.
CREATE TABLE sample_json
AS
SELECT EMPTY_CLOB () || '{ "A" : {"key1":"value1", "key2":"value2", "key3":"value3"} }' AS json_text
FROM DUAL
UNION ALL
SELECT EMPTY_CLOB () || '{ "B" : {"xyz1":"XYZ1"} }' AS json_text FROM DUAL
union all
SELECT EMPTY_CLOB () || '{ "C" : {"somekey":"someval","weird":"strange"} }' AS json_text FROM DUAL;
CREATE TYPE json_rec_t AS OBJECT
(
parent VARCHAR2 (50),
jsonkey VARCHAR2 (50),
jsonvalue VARCHAR2 (50)
);
/
CREATE TYPE json_tab_t IS TABLE OF json_rec_t;
/
CREATE OR REPLACE FUNCTION get_json_vals (p_json CLOB)
RETURN json_tab_t
PIPELINED
AS
l_json json_object_t := json_object_t (p_json);
l_parent_keys json_key_list;
l_child json_object_t;
l_child_keys json_key_list;
BEGIN
l_parent_keys := l_json.get_keys;
FOR i IN 1 .. l_parent_keys.COUNT
LOOP
l_child := l_json.get_object (l_parent_keys (i));
l_child_keys := l_child.get_keys;
FOR j IN 1 .. l_child_keys.COUNT
LOOP
PIPE ROW (json_rec_t (l_parent_keys (i), l_child_keys(j), l_child.get_string(l_child_keys(j))));
END LOOP;
END LOOP;
RETURN;
END;
/
SELECT * FROM sample_json,get_json_vals(json_text);
JSON_TEXT PARENT JSONKEY JSONVALUE
________________________________________________________________ _________ __________ ____________
{ "A" : {"key1":"value1", "key2":"value2", "key3":"value3"} } A key1 value1
{ "A" : {"key1":"value1", "key2":"value2", "key3":"value3"} } A key2 value2
{ "A" : {"key1":"value1", "key2":"value2", "key3":"value3"} } A key3 value3
{ "B" : {"xyz1":"XYZ1"} } B xyz1 XYZ1
{ "C" : {"somekey":"someval","weird":"strange"} } C somekey someval
{ "C" : {"somekey":"someval","weird":"strange"} } C weird strange
Upvotes: 2