使用APEX_JSON阅读JSON

vh0rcniy  于 2023-10-21  发布在  其他
关注(0)|答案(1)|浏览(111)

我一直在尝试解析一个相对简单的JSON结构,但在使用APEX_JSON包时遇到了麻烦。

create table sw_json (theclob clob);
insert into sw_json values (
'{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#directoryObjects(displayName)"
,"value":[
  {"@odata.type":"#microsoft.graph.group","displayName":"Group A"}
 ,{"@odata.type":"#microsoft.graph.group","displayName":"Group B"}
 ,{"@odata.type":"#microsoft.graph.group","displayName":"Group C"}
 ]
}');

在12 c环境中,在Jon Dixon's post的帮助下,我已经能够用SQL中的各种方法解决它。

SELECT name
FROM sw_json
nested theclob.value[*]
columns (name varchar2(100) path '$.displayName')
;

SELECT name
FROM sw_json
left outer join json_table(
   theclob
 , '$.value[*]' columns (name varchar2(100) path '$.displayName')
) on 1=1
;

NAME     
--------
Group A  
Group B  
Group C

然而,为了使它在11 g中也能工作,我尝试只使用APEX_JSON。我成功地使用了感觉像是大锤的方法,但我试图用更直接的路径表达式来整理它。

declare
    l_values apex_json.t_values;
    l_names  APEX_T_VARCHAR2;
    lc_clob  clob;
    lc_index varchar2(200);
    ln_cnt   number := 1;
begin
  select theclob into lc_clob
  from sw_json;

  apex_json.parse (
      p_values => l_values,
      p_source => lc_clob
  );
  dbms_output.put_line('Cnt:'||l_values.count);
  dbms_output.put_line('First:'||l_values.First);
  lc_index := l_values.First;
  for i in 1..l_values.count loop
    lc_index := l_values.next(lc_index);
    exit when lc_index is null;
    -- this seems hacky, relying on data content
    if substr(l_values(lc_index).varchar2_value,1,1) ='#' then 
      lc_index := l_values.next(lc_index);
      dbms_output.put_line(i||':'||l_values(lc_index).varchar2_value);
    end if;
    ln_cnt  := ln_cnt +1;
  end loop;
end;
    /

Cnt:12
First:"@odata.context"
4:Group A
6:Group B
8:Group C

我使用jsonpath.com来验证我的表达式,但我似乎无法将其转换为APEX_JSON用法-我不禁觉得我的想法不正确。

declare
    l_values apex_json.t_values;
    l_names  APEX_T_VARCHAR2;
    lc_clob  clob;
    lc_index varchar2(200);
    ln_cnt   number := 1;
begin
  select theclob into lc_clob
  from sw_json;

  apex_json.parse (
      p_values => l_values,
      p_source => lc_clob
  );
  dbms_output.put_line('Cnt:'||l_values.count);
  dbms_output.put_line('First:'||l_values.First);
  dbms_output.put_line('Test:'||apex_json.get_varchar2(p_path => '$.value.[%d][displayName]', p0 => 1));
  lc_index := l_values.First;
  l_names := apex_json.GET_MEMBERS  (
       p_values => l_values
      -- tried all sorts of variations here to try match the 12c SQL
      ,p_path   => '$.value.[%d][displayName]'
      --, '$.value[*]' columns (id varchar2(100) path '$.displayName')
  );
  dbms_output.put_line('Cnt:'||l_names.count);
  lc_index := l_names.first;
  for i in 1..l_names.count loop
    exit when lc_index is null;
    dbms_output.put_line(ln_cnt||':'||l_names(lc_index));
    lc_index := l_names.next(lc_index);
    ln_cnt  := ln_cnt +1;
  end loop;
end;
/

不管我用什么作为路径表达式,我只是得到一些东西,它向我表明数组返回空。

Cnt:12
First:"@odata.context"
Test:
ORA-06531: Reference to uninitialized collection

尝试稍微不同的循环只返回12个空值

for i in 1..l_values.count loop
    lc_str := apex_json.get_varchar2(p_path => 'value.[%d]displayName', p0 => i);
    dbms_output.put_line(ln_cnt||':'||lc_str);
    ln_cnt  := ln_cnt +1;
  end loop;
bvuwiixz

bvuwiixz1#

APEX_JSON不使用“$.”符号-这是隐含的。以下作品。apex_json.does_exist并不是真正需要的,但它可以防止抛出异常。

declare
    l_values apex_json.t_values;
    l_names  APEX_T_VARCHAR2;
    lc_clob  clob;
    lc_index varchar2(200);
    ln_cnt   number := 1;
begin
  select theclob into lc_clob
  from sw_json;

  apex_json.parse (
      p_values => l_values,
      p_source => lc_clob
  );
  dbms_output.put_line('Member of value array:'||apex_json.get_count(p_path => 'value', p_values => l_values));
  IF apex_json.does_exist(p_path => 'value',p_values => l_values) THEN
     FOR r IN 1 .. apex_json.get_count(p_path => 'value', p_values => l_values) LOOP
       dbms_output.put_line(apex_json.get_varchar2(p_path => 'value[%d].displayName', p0 => r, p_values => l_values));
     END LOOP;
  END IF;

end;
/

Member of value array:3
Group A
Group B
Group C

相关问题