使用 APEX_JSON 读取 JSON

问题描述 投票:0回答:1

我一直在尝试解析我认为相对简单的 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"}
 ]
}');

在12c环境中,在Jon Dixon帖子的帮助下,我已经能够在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  

但是,为了使其在 11g 中也能工作,我尝试仅使用 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;
json oracle-apex
1个回答
0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.