简体   繁体   中英

Parse Json using Oracle SQL - JSON_TABLE

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:

在此处输入图像描述

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).

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 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM