2011-11-02 47 views
19

Có cách nào dễ dàng để làm việc với JSON trong oracle? Tôi có một quy trình chuẩn mà tôi thường sử dụng để gọi các dịch vụ web, JSON là một định dạng mà tôi quen thuộc trong ngữ cảnh phát triển web, nhưng cách tốt nhất để làm việc với json trong một thủ tục được lưu trữ là gì? Ví dụ, lấy đáp ứng CLOB từ URI, chuyển đổi nó thành một đối tượng JSON và nhận được một giá trị từ đó?làm việc với json trong oracle

Vì tham khảo, đây là thủ tục tôi đã sử dụng để lấy URL

create or replace procedure macp_URL_GET(url_resp in out clob, v_url in varchar2) is 
    req  Utl_Http.req; 
    resp Utl_Http.resp; 
    NAME VARCHAR2 (255); 
    VALUE VARCHAR2 (1023); 
    v_msg VARCHAR2 (80); 
    v_ans clob; 
-- v_url VARCHAR2 (32767) := 'http://www.macalester.edu/'; 
BEGIN 
    /* request that exceptions are raised for error Status Codes */ 
    Utl_Http.set_response_error_check (ENABLE => TRUE); 
    /* allow testing for exceptions like Utl_Http.Http_Server_Error */ 
    Utl_Http.set_detailed_excp_support (ENABLE => TRUE); 
    /* 
    Utl_Http.set_proxy (
     proxy     => 'www-proxy.us.oracle.com', 
     no_proxy_domains  => 'us.oracle.com' 
    ); 
    */ 
    req := Utl_Http.begin_request (url => v_url, method => 'GET'); 
    /* 
    Alternatively use method => 'POST' and Utl_Http.Write_Text to 
    build an arbitrarily long message 
    */ 

    /* 
    Utl_Http.set_authentication (
     r    => req, 
     username  => 'SomeUser', 
     PASSWORD  => 'SomePassword', 
     scheme   => 'Basic', 
     for_proxy  => FALSE  --this info is for the target Web server 
    ); 
    */ 

    Utl_Http.set_header (r => req, NAME => 'User-Agent', VALUE => 'Mozilla/4.0'); 
    resp := Utl_Http.get_response (r => req); 
    /* 
    DBMS_OUTPUT.put_line ('Status code: ' || resp.status_code); 
    DBMS_OUTPUT.put_line ('Reason phrase: ' || resp.reason_phrase); 
    FOR i IN 1 .. Utl_Http.get_header_count (r => resp) 
    LOOP 
     Utl_Http.get_header (r => resp, n => i, NAME => NAME, VALUE => VALUE); 
     DBMS_OUTPUT.put_line (NAME || ': ' || VALUE); 
    END LOOP; 
    */ 
--test 
    BEGIN 
     LOOP 
     Utl_Http.read_text (r => resp, DATA => v_msg); 
     --DBMS_OUTPUT.put_line (v_msg); 
     v_ans := v_ans || v_msg; 
     url_resp := url_resp || v_msg; 
     END LOOP; 
    EXCEPTION 
     WHEN Utl_Http.end_of_body 
     THEN 
     NULL; 
    END; 
--test 
    Utl_Http.end_response (r => resp); 


    --url_resp := v_ans; 

EXCEPTION 
    /* 
    The exception handling illustrates the use of "pragma-ed" exceptions 
    like Utl_Http.Http_Client_Error. In a realistic example, the program 
    would use these when it coded explicit recovery actions. 

    Request_Failed is raised for all exceptions after calling 
    Utl_Http.Set_Detailed_Excp_Support (ENABLE=>FALSE) 
    And it is NEVER raised after calling with ENABLE=>TRUE 
    */ 
    WHEN Utl_Http.request_failed 
    THEN 
     DBMS_OUTPUT.put_line (
     'Request_Failed: ' || Utl_Http.get_detailed_sqlerrm 
    ); 
     url_resp :='Request_Failed: ' || Utl_Http.get_detailed_sqlerrm; 
    /* raised by URL http://xxx.oracle.com/ */ 
    WHEN Utl_Http.http_server_error 
    THEN 
     DBMS_OUTPUT.put_line (
     'Http_Server_Error: ' || Utl_Http.get_detailed_sqlerrm 
    ); 
     url_resp := 'Http_Server_Error: ' || Utl_Http.get_detailed_sqlerrm; 
    /* raised by URL http://otn.oracle.com/xxx */ 
    WHEN Utl_Http.http_client_error 
    THEN 
     DBMS_OUTPUT.put_line (
     'Http_Client_Error: ' || Utl_Http.get_detailed_sqlerrm 
    ); 
     url_resp := 'Http_Client_Error: ' || Utl_Http.get_detailed_sqlerrm; 
    /* code for all the other defined exceptions you can recover from */ 
    WHEN OTHERS 
    THEN 
     DBMS_OUTPUT.put_line (SQLERRM); 
     url_resp := SQLERRM; 
END; 

Sau đó, để kiểm tra nó

begin 
    macp_url_get(url_resp => :url_resp, 
       'http://maps.googleapis.com/maps/api/geocode/json?address=55105&sensor=false'); 
end; 

(Tôi biết rằng googleapi sẽ cho phép phản ứng xml, nhưng có khác các API web mà tôi sử dụng thường xuyên mặc định là JSON)

+1

Tôi không nghĩ bạn có thể thực hiện việc này, nhưng có một số người đã tạo ra api cho nó [ http://reseau.erasme.org/pl-sql-library-for-JSON?lang=en] (thư viện pl/sql cho JSON - bạn có thể xem xét ví dụ, trông khá thẳng về phía trước) & [ sourceforge.net/projects/pljson/] (pljson - điều này có vẻ phức tạp hơn nhưng cũng nên hoạt động) – Harrison

Trả lời

18

Tôi đã bắt đầu sử dụng thư viện này và có vẻ như hứa hẹn: https://github.com/pljson/pljson

Dễ cài đặt và các ví dụ là tốt.

Để sử dụng thư viện trong ví dụ của bạn, thêm các biến này để làm thủ ..

mapData  json; 
results  json_list; 
status  json_value; 
firstResult json; 
geometry json; 

....

Sau đó, bạn có thể thao tác các phản ứng như một đối tượng JSON.

-- convert the result from the get to a json object, and show some results. 
mapData := json(v_ans); 

-- Show the status of the request 
status := mapData.get('status'); 
dbms_output.put_line('Status = ' || status.get_string()); 

IF (status.get_string() = 'OK') THEN 
    results := json_list(mapData.get('results')); 
    -- Grab the first item in the list 
    resultObject := json(results.head); 

    -- Show the human readable address 
    dbms_output.put_line('Address = ' || resultObject.get('formatted_address').to_char()); 
    -- Show the json location data 
    dbms_output.put_line('Location = ' || resultObject.get('geometry').to_char()); 
END IF; 

Chạy này mã sẽ đầu ra này để đầu ra DBMS:

Status = OK 
Address = "St Paul, MN 55105, USA" 
Location = { 
    "bounds" : { 
    "northeast" : { 
     "lat" : 44.9483849, 
     "lng" : -93.1261959 
    }, 
    "southwest" : { 
     "lat" : 44.9223829, 
     "lng" : -93.200307 
    } 
    }, 
    "location" : { 
    "lat" : 44.9330076, 
    "lng" : -93.16290629999999 
    }, 
    "location_type" : "APPROXIMATE", 
    "viewport" : { 
    "northeast" : { 
     "lat" : 44.9483849, 
     "lng" : -93.1261959 
    }, 
    "southwest" : { 
     "lat" : 44.9223829, 
     "lng" : -93.200307 
    } 
    } 
} 
+1

Cần lưu ý rằng thư viện này đã chuyển sang GitHub https://github.com/pljson/pljson – Damian

2

Tôi đã viết thư viện này: http://reseau.erasme.org/pl-sql-library-for-JSON?lang=en và hoạt động tốt để nhận phản hồi json vào bảng plsql.

Nếu bạn chỉ muốn trích xuất dữ liệu Oracle và biến nó trong Json, thư viện này là một chút "nặng để sử dụng" ... tôi có thể đề nghị bạn mã khác làm việc đó tốt hơn và nhanh hơn:

create or replace package jsonfly as 

procedure open_object(k varchar2 default null); 
procedure close_object; 
procedure open_array (k varchar2 default null); 
procedure close_array; 
procedure separation; 
procedure member(k varchar2, v varchar2); 
procedure member(k varchar2, n number); 
procedure send; 
end; 
/

create or replace package body jsonfly as 
-------------------------------------------------------------------------------- 
-- package pour générer du JSON, envoyé à la volé 
-------------------------------------------------------------------------------- 
type tCache is table of varchar2(2000) index by binary_integer; 

g_openBrace   constant varchar2(2) := '{ '; 
g_closeBrace  constant varchar2(2) := ' }'; 
g_openBracket  constant varchar2(2) := '[ '; 
g_closeBracket  constant varchar2(2) := ' ]'; 
g_stringDelimiter constant varchar2(1) := '"'; 
g_Affectation  constant varchar2(3) := ' : '; 
g_separation  constant varchar2(3) := ', '; 
g_CR    constant varchar2(1) := Chr(10); -- used to indent the JSON object correctly 
g_spc    constant varchar2(2) := ' ';  -- used to indent the JSON object correctly 
g_js_comment_open constant varchar2(20) := '/*-secure-\n'; -- used to prevent from javascript hijacking 
g_js_comment_close constant varchar2(20) := '\n*/';   -- used to prevent from javascript hijacking 

--isObjectOpened boolean := false; 
--isArrayOpened boolean := false; 
t tCache; 
i number := 1; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure p(s varchar2) is 
begin 
    t(i) := s; 
    i := i + 1; 
end; 
-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
function encap (s varchar2) return varchar2 is 
begin 
    return g_stringdelimiter || s || g_stringdelimiter; 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
function encode_string(p_string varchar2) return varchar2 is 
begin 
    return replace(replace(replace(replace(replace(replace(replace(replace(p_string, 
     '\', '\\'), 
     '"', '\"'), 
     '/', '\/'), 
     chr(8), '\b'), 
     chr(9), '\t'), 
     chr(10), '\n'), 
     chr(12), '\f'), 
     chr(13), '\r'); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure open_object(k varchar2 default null) is 
begin  
    if (k is null) then 
     p(g_openbrace); 
    else 
     p(encap(k) || g_affectation || g_openbrace); 
    end if; 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure close_object is 
begin 
    if (t(i-1) = g_separation) then 
     i := i - 1; 
    end if; 
    p(g_closebrace); 
    separation(); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure open_array (k varchar2 default null) is 
begin  
    if (k is null) then 
    p(g_openbracket); 
    else 
     p(encap(k) || g_affectation || g_openbracket); 
    end if; 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure close_array is 
begin 
    if (t(i-1) = g_separation) then 
     i := i - 1; 
    end if; 
    p(g_closebracket); 
    separation(); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure separation is 
begin 
    p(g_separation); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure key(k varchar2) is 
begin 
    p(encap(k) || g_affectation); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure value(v varchar2) is 
begin 
    p(v); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure member(k varchar2, v varchar2) is 
begin 
    p(encap(k) || g_affectation || encap(encode_string(v))); 
    p(g_separation); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure member(k varchar2, n number) is 
begin 
    p(encap(k) || g_affectation || n); 
    p(g_separation); 
end; 

-------------------------------------------------------------------------------- 
-- 
-------------------------------------------------------------------------------- 
procedure send is 
begin 
    if (t(i-1) = g_separation) then 
     t.delete(i-1); 
    end if; 

    i := t.first; 
    while (i is not null) loop 
     htp.p(t(i)); 
     i := t.next(i); 
    end loop; 
end; 


end jsonfly; 
/
3

Cần lưu ý rằng như của Oracle 12c có một số hỗ trợ bản địa của JSON. Tuy nhiên tôi không nghĩ rằng trong hình thức hiện tại nó là hữu ích như giống như của PLJSON bao gồm trong một câu trả lời.

Để sử dụng tính năng bạn tạo bảng có trường BLOB, CLOB hoặc Varchar2 và thêm ràng buộc vào trường "cột IS JSON". Điều này thực thi kiểm tra cú pháp JSON trên cột đó.

Miễn là ràng buộc "IS JSON" được đặt ra, bạn có thể truy cập các giá trị JSON bên trong sử dụng ký pháp chấm từ SQL. Đối với tôi, nó dường như không cung cấp thao tác mạnh như PLJSON. Bạn cũng có thể tạo một XMLType và sau đó chuyển đổi sang JSON.

Liên kết hữu ích:
Oracle docs
Good tutorial and examples
Tutorial including XML to JSON

1

Oracle APEX 5.0 đã hỗ trợ cho JSON sử dụng APEX_JSON gói. Tôi đã không sử dụng nó nhưng có vẻ thú vị và tôi đã yêu cầu nhóm của tôi khám phá nó.Trường hợp sử dụng của chúng tôi là có thể truyền dữ liệu JSON làm tham số đầu vào cho thủ tục được lưu trữ từ ứng dụng nodejs.

+0

Nó không thẳng mong muốn cài đặt gói APEX_JSON vào cơ sở dữ liệu thoát của chúng tôi mà không cần cài đặt máy chủ APEX 5.0. Chúng tôi quyết định sử dụng thư viện pljson (https://github.com/pljson/pljson). – Parvez

1

Oracle 12c bây giờ có native JSON support:

Oracle Database hỗ trợ đối tượng JavaScript Notation (JSON) dữ liệu nguyên bản với các tính năng cơ sở dữ liệu quan hệ, bao gồm các giao dịch, lập chỉ mục, truy vấn khai báo, vì thế quan điểm

dữ liệu JSON và dữ liệu XML có thể được sử dụng trong Oracle Database theo những cách tương tự. Không giống như dữ liệu quan hệ, cả hai có thể được lưu trữ, lập chỉ mục và truy vấn mà không cần bất kỳ một lược đồ nào xác định dữ liệu. Cơ sở dữ liệu Oracle hỗ trợ JSON nguyên bản với các tính năng cơ sở dữ liệu quan hệ, bao gồm các giao dịch, lập chỉ mục, truy vấn khai báo và các khung nhìn.

Dữ liệu JSON thường được lưu trữ trong cơ sở dữ liệu NoSQL như Cơ sở dữ liệu Oracle NoSQL và Oracle Berkeley DB. Chúng cho phép lưu trữ và truy xuất dữ liệu không dựa trên bất kỳ lược đồ nào, nhưng chúng không cung cấp các mô hình thống nhất chặt chẽ của các cơ sở dữ liệu quan hệ.

Để bù đắp cho thiếu sót này, cơ sở dữ liệu quan hệ đôi khi được sử dụng song song với cơ sở dữ liệu NoSQL. Các ứng dụng sử dụng dữ liệu JSON được lưu trữ trong cơ sở dữ liệu NoSQL sau đó phải đảm bảo tính toàn vẹn của dữ liệu.

Hỗ trợ gốc cho JSON bởi Cơ sở dữ liệu Oracle tránh được các cách giải quyết như vậy. Nó cung cấp tất cả các lợi ích của các tính năng cơ sở dữ liệu quan hệ để sử dụng với JSON, bao gồm các giao dịch, lập chỉ mục, truy vấn khai báo và các khung nhìn.

Truy vấn cơ sở dữ liệu Oracle là khai báo. Bạn có thể tham gia dữ liệu JSON với dữ liệu quan hệ. Và bạn có thể chiếu dữ liệu JSON một cách có liên quan, làm cho nó có sẵn cho các quy trình và công cụ quan hệ. Bạn cũng có thể truy vấn, từ bên trong cơ sở dữ liệu, dữ liệu JSON được lưu trữ bên ngoài cơ sở dữ liệu trong một bảng bên ngoài.

Bạn có thể truy cập dữ liệu JSON được lưu trữ trong cơ sở dữ liệu giống như cách bạn truy cập dữ liệu cơ sở dữ liệu khác, bao gồm sử dụng OCI, .NET và JDBC.

Không giống như dữ liệu XML, được lưu trữ bằng cách sử dụng kiểu dữ liệu SQL XMLType, dữ liệu JSON được lưu trữ trong cơ sở dữ liệu Oracle sử dụng các kiểu dữ liệu SQL VARCHAR2, CLOB và BLOB. Oracle khuyến cáo rằng bạn luôn sử dụng ràng buộc kiểm tra is_json để đảm bảo rằng các giá trị cột là các trường hợp JSON hợp lệ

Các vấn đề liên quan