2017-01-31 3 views
0

У меня есть объект JSON, хранящийся в CLOB, который представляет иерархию:Архиерейский JSON к оракулу таблице

{ 
    "Version": 1, 
    "nodes": [{ 
      "id": 0, 
      "Fields": ["ABC"], 
      "nodes": [{ 
        "id": 1, 
        "Fields": ["DEF"], 
        "nodes": [{ 
          "id": 2, 
          "Fields": ["GHI", "HIG"], 
          "nodes": [] 
         } 
        ] 
       }, { 
        "id": 3, 
        "Fields": ["XYZ", "YZX"], 
        "nodes": [{ 
          "id": 4, 
          "Fields": ["UVW"], 
          "nodes": [{ 
            "id": 5, 
            "Fields": ["RST"], 
            "nodes": [] 
           } 
          ] 
         } 
        ] 
       } 
      ] 
     } 
    ] 
} 

Мне нужно, чтобы представить это в виде таблицы:

Ver id Field Parent 
    1 0 ABC  null 
    1 1 DEF   0 
    1 2 GHI|HIG  1 
    1 3 XYZ|YZX  0 
    1 4 UVW   3 
    1 5 RST   4 

Я попытался с помощью PL/JSON. Хотя я могу найти отдельные точки данных, я столкнулся с трудностями с иерархической природой.

APEX (и 12c) не является вариантом.

Может ли кто-нибудь помочь в этом?

+0

У вас есть возможность перейти на Oracle 12c? Они представили [JSON в Oracle Database] (https://docs.oracle.com/database/121/ADXDB/json.htm#ADXDB624) и [Функции JSON] (http://docs.oracle.com/database/121 /SQLRF/functions002.htm#SQLRF56667) –

+0

@WernfriedDomscheit Это в конвейере, но это должно произойти до того, как это произойдет. – JohnHC

+0

Я не знаю, решает ли это вашу проблему, но посмотрите на ветку 'develop'. У нас есть реализация таблицы - https://github.com/pljson/pljson/blob/20022b5bdad742690226d3b73a8d244d67cfc85c/src/addons/pljson_table_impl.type.decl.sql –

ответ

1

Я пишу синтаксический анализатор jSON с pl \ sql. Не могли бы вы проверить его и принять.

declare 
    type t_str_rec is table of varchar2(4000); 
    type t_str_str is table of t_str_rec; 
    l_tab t_str_str := t_str_str(); 
    l_count number := 0; 
    procedure get_number (p_value clob, 
         p_offset out number, 
         p_number out varchar2) is 
    l_cur_var varchar2(1 char); 
    begin 
    p_offset := 1; 
    l_cur_var := dbms_lob.substr(p_value,1,1); 
    while l_cur_var IN ('0','1','2','3','4','5','6','7','8','9') loop 
     l_cur_var := dbms_lob.substr(p_value,1,p_offset); 
     p_offset := p_offset + 1; 
    end loop; 
    p_number := dbms_lob.substr(p_value,p_offset-2,1); 
    p_offset := p_offset-2; 
-- dbms_output.put_line('get_number:'||p_offset); 
    end; 
    procedure get_q_string (p_value clob, 
          p_offset out number, 
          p_string out varchar2) is 
    l_cur_pos number; 
    l_cur_var varchar2(1 char); 
    l_count_quotes number := 0; 
    l_is_end number := 0; 
    begin 
    p_offset := 1; 
    while l_is_end = 0 loop 
     p_offset := dbms_lob.instr(p_value,'"',p_offset + 1); 
     l_cur_var := dbms_lob.substr(p_value,1,p_offset-1); 
     while l_cur_var = '\' loop 
     l_count_quotes := l_count_quotes +1; 
     l_cur_pos := l_cur_pos-1; 
     l_cur_var := dbms_lob.substr(p_value,1,l_cur_pos-1); 
     end loop; 
     if(mod(l_count_quotes,2) = 0) then 
     l_is_end := 1; 
     end if; 
    end loop; 
    p_string := dbms_lob.substr(p_value,p_offset-2,2); 
-- dbms_output.put_line('get_q_string:'||p_offset|| ':'||length(p_string)); 
    end; 
    procedure get_one_bracket(p_value clob, 
          p_bracket varchar2 := '[]', 
          p_offset out number) is 
    l_left varchar2(1 char) := substr(p_bracket,1,1); 
    l_right varchar2(1 char) := substr(p_bracket,2,1); 
    l_cur_pos number; 
begin 
    l_cur_pos := 1; 
    p_offset := dbms_lob.instr(p_value,l_right); 
    l_cur_pos := dbms_lob.instr(p_value,l_left,l_cur_pos+1); 
    while l_cur_pos > 0 and l_cur_pos < p_offset loop 
     l_cur_pos := dbms_lob.instr(p_value,l_left,l_cur_pos+1); 
     p_offset := dbms_lob.instr(p_value,l_right,p_offset+1); 
     if p_offset < 1 then 
      p_offset := dbms_lob.getlength(p_value); 
      exit; 
     end if; 
    end loop; 
-- p_offset := p_offset-1; 
-- dbms_output.put_line('get_one_bracket:'|| p_bracket||':'||p_offset); 
    end; 
    procedure parse_json (p_clob clob 
         , p_parent number) is 
    l_pos number := 1; 
    l_offset number := 1; 
    l_length number := dbms_lob.getlength(p_clob); 
    l_cur_char varchar2(1 char); 
    l_rec t_str_rec := t_str_rec(); 
    l_parent number := p_parent; 
    begin 
    while(l_pos < l_length) loop 
     l_cur_char := dbms_lob.substr(p_clob, 1,l_pos); 
     if l_cur_char = '"' then 
      l_rec.extend(); 
      get_q_string(dbms_lob.substr(p_clob, l_length-l_pos, l_pos), 
         l_offset, 
         l_rec(l_rec.last)); 
     elsif l_cur_char = ':' then null; -- it's just a separator 
     elsif l_cur_char IN ('0','1','2','3','4','5','6','7','8','9') then 
     l_rec.extend(); 
     get_number (dbms_lob.substr(p_clob, l_length-l_pos, l_pos), 
        l_offset, 
        l_rec(l_rec.last)); 
     elsif l_cur_char = '{' then 
     l_rec.extend(); 
     l_rec(l_rec.last) := '{}'; 
     get_one_bracket(dbms_lob.substr(p_clob, l_length-l_pos+1, l_pos), 
         '{}', 
         l_offset); 
     declare 
      l_id number := l_count; 
     begin 
      parse_json (dbms_lob.substr(p_clob, l_offset, l_pos+1), 
         l_id); 
     end; 
     elsif l_cur_char = '[' then 
     l_rec.extend(); 
     l_rec(l_rec.last) := '[]'; 
     get_one_bracket(dbms_lob.substr(p_clob, l_length-l_pos+1, l_pos), 
         '[]', 
         l_offset); 
     l_rec.extend(); 
     l_count := l_count + 1; 
     l_rec(l_rec.last) := l_count; 
     l_rec.extend(); 
     l_rec(l_rec.last) := l_parent; 
     l_tab.extend; 
     l_tab(l_tab.last) := l_rec; 
     l_rec := t_str_rec(); 
     declare 
      l_id number := l_count; 
     begin 
      parse_json (dbms_lob.substr(p_clob, l_offset, l_pos+1), 
         l_id); 
     end; 
     elsif l_cur_char = ',' then 
     IF dbms_lob.substr(p_clob, 1,l_pos-1) NOT IN (']','}',',') then 
      l_rec.extend(); 
      l_count := l_count + 1; 
      l_rec(l_rec.last) := l_count; 
      l_rec.extend(); 
      l_rec(l_rec.last) := l_parent; 

      l_tab.extend; 
      l_tab(l_tab.last) := l_rec; 

      l_rec := t_str_rec(); 
     end if; 
     end if; 
     l_pos := l_pos+l_offset; 
     l_offset := 1; 
    end loop; 
    l_rec.extend(); 
    l_count := l_count + 1; 
    l_rec(l_rec.last) := l_count; 
    l_rec.extend(); 
    l_rec(l_rec.last) := l_parent; 
    l_tab.extend; 
    l_tab(l_tab.last) := l_rec; 
    l_rec := t_str_rec(); 
    end; 
begin 
    parse_json( 
'{ 
    "Version": 1, 
    "nodes": [{ 
      "id": 0, 
      "Fields": ["ABC"], 
      "nodes": [{ 
        "id": 1, 
        "Fields": ["DEF"], 
        "nodes": [{ 
          "id": 2, 
          "Fields": ["GHI", "HIG"], 
          "nodes": [] 
         } 
        ] 
       }, { 
        "id": 3, 
        "Fields": ["XYZ", "YZX"], 
        "nodes": [{ 
          "id": 4, 
          "Fields": ["UVW"], 
          "nodes": [{ 
            "id": 5, 
            "Fields": ["RST"], 
            "nodes": [] 
           } 
          ] 
         } 
        ] 
       } 
      ] 
     } 
    ] 
}',l_count); 
    declare 
     v_vers varchar2(10); 
     v_id varchar2(10) ; 
     v_field varchar2(4000); 
     v_del varchar2(1); 
     v_is_field number; 
     v_parent varchar2(10); 
     type t_num_decode is table of varchar2(10) index by varchar2(10); 
     l_num_decode t_num_decode; 
    begin 
     for ba in l_tab.first .. l_tab.last loop 
      if v_vers is null and l_tab(ba)(1) = 'Version' then 
      v_vers := l_tab(ba)(2); 
      end if; 
      if l_tab(ba)(1) = 'id' then 
      v_id := l_tab(ba)(2); 
      elsif l_tab(ba)(1) = 'Fields' then 
      v_is_field := 1; 
      v_field := ''; 
      elsif l_tab(ba)(1) = 'nodes' and v_id is not null then 
       if l_num_decode.exists(l_tab(ba)(4)) then 
       v_parent := l_num_decode(l_tab(ba)(4)); 
       end if; 
       dbms_output.put_line(v_vers||','||v_id||','||v_field||','||nvl(v_parent,'null')); 
       l_num_decode(l_tab(ba)(3)) := v_id; 
       v_is_field := 0; 
       v_del := ''; 
      elsif v_is_field = 1 then 
      v_field := v_field||v_del||l_tab(ba)(1); 
      v_del := '|'; 
      end if; 
     end loop; 
    end; 
end; 
/
+0

Я думаю, что люблю тебя ... Отлично, спасибо – JohnHC

Смежные вопросы