Reputation: 35
I am trying to parse JSON using JSON_TABLE.
Oracle DB version 12.1.0.2
{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{
"mName" : "Carol",
"lName" : "Cena"
},
{
"mName" : "Mark",
"lName" : "Karlo"
}
]
}
Tried with below query but not getting expected result.
select * from json_Table(
'{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{"mName" : "Carol","lName" : "Cena"},
{"mName" : "Mark","lName" : "Karlo"}
]
}',
'$' columns ( rownr number path '$.Rownum',
name varchar2(100) path '$.Name',
nested path '$.TextObj[*]' columns (mName varchar2(100) path '$.mName',
lName varchar2(100) path '$.lName'
),
nested path '$.AddressArray[*]' columns(AddressArray varchar2(100) path '$')
)
);
Output from above query:
Expected output:
Upvotes: 2
Views: 3194
Reputation:
You seem to want a cross join of the array values (grouped by rownum
and name
). This is not a standard JSON structure, so you shouldn't expect to be able to do this with a single application of json_table
.
Here is one way to do this with two calls to json_table
. In the first call, you use a nested path to get just the names, but you still keep the address arrays. In a second call, you unpack the addresses, separately for each row produced by the first call.
Note the use of an optimizer hint in the outer select
. This is needed, because without it the optimizer will try an illegal "unnesting" of the lateral join (outer apply
) and then throw an error, instead of leaving the query as is. (This is a very common and annoying habit of the optimizer: it tries something that is invalid, and then it complains about it.)
Also, rownum
is a reserved keyword - you can't use it as a column name in the output. (Technically you can, with additional work, but it is best to believe that you can't.)
with
t as (
select *
from json_Table(
'{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{"mName" : "Carol","lName" : "Cena"},
{"mName" : "Mark","lName" : "Karlo"}
]
}',
'$' columns (
rownr number path '$.Rownum',
name varchar2(100) path '$.Name',
addressArray varchar2(4000) format json path '$.AddressArray',
nested path '$.TextObj[*]'
columns (mName varchar2(100) path '$.mName',
lName varchar2(100) path '$.lName'
)
)
)
)
select /*+ no_query_transformation */ rownr, name, mname, lname, address
from t
outer apply
json_table (t.addressArray, '$[*]'
columns (address varchar2(10) path '$')
)
;
Output:
ROWNR NAME MNAME LNAME ADDRESS
----- ------ ------ ------ ----------
1 John Carol Cena Address1
1 John Carol Cena Address2
1 John Mark Karlo Address1
1 John Mark Karlo Address2
Upvotes: 1
Reputation: 191570
You could chain several json_table
calls:
select j1.rnum, j1.name, j2.address, j3.mName, j3.lName
from (
select '{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{
"mName" : "Carol",
"lName" : "Cena"
},
{
"mName" : "Mark",
"lName" : "Karlo"
}
]
}' as str
from dual
) t
outer apply json_table (
t.str format json, '$'
columns (
rNum number path '$.Rownum',
name varchar2(10) path '$.Name',
addressArray varchar2(4000) format json path '$.AddressArray',
textObj varchar2(4000) format json path '$.TextObj'
)
) j1
outer apply json_table (
j1.addressArray, '$[*]'
columns (
address varchar2(10) path '$'
)
) j2
outer apply json_table (
j1.textObj, '$[*]'
columns (
mName varchar2(10) path '$.mName',
lName varchar2(10) path '$.lName'
)
) j3
where t
is just an inline view to supply your sample JSON as a str
column, which is then processed by the first json_table
. That gets the rownumber and name values, and also the address array which is passed to the second json_table
, and the text object which is passed to the third json_table
. Those produce the values from their arrays.
RNUM | NAME | ADDRESS | MNAME | LNAME
---: | :--- | :------- | :---- | :----
1 | John | Address1 | Carol | Cena
1 | John | Address1 | Mark | Karlo
1 | John | Address2 | Carol | Cena
1 | John | Address2 | Mark | Karlo
db<>fiddle (18c, but verified on 12cR1).
Upvotes: 1