I need to parse JSON to a table or array. As this is completely new for me I've used Google for help but something is not working for me :/
My JSON looks like:
{
"statusCode": 200,
"isValid": true,
"errors": [],
"result": {
"optimizationData": [
{
"name": "out",
"content": "ID_LIMIT;TIME_STAMP_FROM;DIRECTION;ID_MODEL_CONSTRAINT\n1;202109222200;G;2_7_1_G\n1;202109232200;G;2_3_1_G\n2;202109222200;G;2_3_1_G\n3;202109222200;G;3_3_1_P\n"
},
{
"name": "unit_out",
"content": "ID_LIMIT;CODE_UNIT;TIME_STAMP_FROM;TIME_STAMP_TO;VARIABLE;VALUE\n1;BEL 2-02;202109222200;202109232200;RelaxationPlus;10\n1;BEL 2-05;202109222200;202109232200;RelaxationPlus;10\n2;WLO 1-01;202109222200;202109232200;RelaxationMinus;10\n"
}
]
}
}
From above JSON I'd like to create table (or arrays) like below (example expected data for name: "unit_out"):
ID_LIMIT | CODE_UNIT | TIME_STAMP_FROM | TIME_STAMP_TO | VARIABLE | VALUE |
---|---|---|---|---|---|
1 | BEL 2-02 | 202109222200 | 202109232200 | RelaxationPlus | 10 |
1 | BEL 2-05 | 202109222200 | 202109232200 | RelaxationPlus | 10 |
2 | WLO 1-01 | 202109222200 | 202109232200 | RelaxationMinus | 10 |
So far I've tried to wrote a function to return "content" value, but I'm getting ORA-30625 (method dispatch on null self argument is disallowed)
CREATE OR REPLACE FUNCTION parse_json (json IN VARCHAR2)
RETURN VARCHAR2 IS
json_obj_in JSON_OBJECT_T;
json_arr JSON_ARRAY_T;
json_elem JSON_ELEMENT_T;
json_obj JSON_OBJECT_T;
name varchar2(32000);
content varchar2(32000);
BEGIN
json_obj_in := JSON_OBJECT_T.parse(json);
json_arr := json_obj_in.get_Array('result');
FOR i IN 0 .. json_arr.get_size - 1 --NVL(json_arr.FIRST, 1) .. NVL(json_arr.LAST, 0)
LOOP
json_obj := JSON_OBJECT_T(json_arr.get(i));
name := json_obj.get_Object('optimizationData').get_string('name');
content := json_obj.get_Object('optimizationData').get_string('content');
END LOOP;
RETURN json_obj_in.to_string;
END;
I'm not sure what's wrong or if my approach to this task is correct.
Can anyone help?
Thanks
CodePudding user response:
From Oracle 12, you can do all the parsing in an SQL query. Your main issue is not the JSON but that you have your data in strings and you will need to split those into lines and then into value and correlate the values with the headers:
SELECT p.*
FROM (
SELECT l.lineno,
kv.key,
kv.value
FROM table_name t
CROSS APPLY JSON_TABLE(
t.value,
'$.result.optimizationData[*]?(@.name == "unit_out")'
COLUMNS
content CLOB PATH '$.content'
) j
CROSS JOIN LATERAL (
SELECT LEVEL AS lineno,
REGEXP_SUBSTR(j.content, '. ', 1, 1 ) AS header,
REGEXP_SUBSTR(j.content, '. ', 1, LEVEL ) AS line
FROM DUAL
WHERE LEVEL > 1
CONNECT BY LEVEL <= REGEXP_COUNT(j.content, '. ')
) l
CROSS JOIN LATERAL (
SELECT CAST(REGEXP_SUBSTR(header, '[^;] ', 1, LEVEL) AS VARCHAR2(4000))
AS key,
CAST(REGEXP_SUBSTR(line, '[^;] ', 1, LEVEL) AS VARCHAR2(4000))
AS value
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT(header, '[^;] ')
) kv
) pt
PIVOT (
MAX(value)
FOR key IN (
'ID_LIMIT' AS id_limit,
'CODE_UNIT' AS code_limit,
'TIME_STAMP_FROM' AS time_stamp_from,
'TIME_STAMP_TO' AS time_stamp_to,
'VARIABLE' AS variable,
'VALUE' AS value
)
) p
Which, for the sample data:
CREATE TABLE table_name (value BLOB CHECK (value IS JSON));
INSERT INTO table_name (value) VALUES (
'{
"statusCode": 200,
"isValid": true,
"errors": [],
"result": {
"optimizationData": [
{
"name": "out",
"content": "ID_LIMIT;TIME_STAMP_FROM;DIRECTION;ID_MODEL_CONSTRAINT\n1;202109222200;G;2_7_1_G\n1;202109232200;G;2_3_1_G\n2;202109222200;G;2_3_1_G\n3;202109222200;G;3_3_1_P\n"
},
{
"name": "unit_out",
"content": "ID_LIMIT;CODE_UNIT;TIME_STAMP_FROM;TIME_STAMP_TO;VARIABLE;VALUE\n1;BEL 2-02;202109222200;202109232200;RelaxationPlus;10\n1;BEL 2-05;202109222200;202109232200;RelaxationPlus;10\n2;WLO 1-01;202109222200;202109232200;RelaxationMinus;10\n"
}
]
}
}'
);
Outputs:
LINENO ID_LIMIT CODE_LIMIT TIME_STAMP_FROM TIME_STAMP_TO VARIABLE VALUE 2 1 BEL 2-02 202109222200 202109232200 RelaxationPlus 10 3 1 BEL 2-05 202109222200 202109232200 RelaxationPlus 10 4 2 WLO 1-01 202109222200 202109232200 RelaxationMinus 10
db<>fiddle here
CodePudding user response:
I'm leaving you with an example that worked for me in Oracle 12c
:
INSERT INTO table(param_id, name, label, parameterIndex, notNull, parameterTypeName, default_value, lov_query)
SELECT param_id, name, label, parameterIndex, notNull, parameterTypeName, default_value, lov_query FROM JSON_TABLE(l_json,
'$.parameters[*]' COLUMNS (
param_id PATH '$.id', name PATH '$.name',
label PATH '$.label',
parameterIndex PATH '$.parameterIndex',
notNull PATH '$.notNull',
parameterTypeName PATH '$.parameterType.parameterTypeName',
default_value PATH '$.parameterAttributes.attributeSelectedOption.attributeValue',
lov_query PATH '$.parameterQuery'
) );
I don't know if it's considered a good practice and somebody do correct me if I'm wrong. This worked for me.