Oracle Rest Data Service return 一个集合 JSON

Oracle Rest Data Service return a collection as JSON

我在一个集合中有一些数据,我想将其作为结果集发送到响应正文中。

是否可以将关联数组解析为 JSON,然后将其作为结果集发送?

根据要求,让我向您展示如何使用嵌入类型的集合来创建 json 并通过 Web 休息服务交付它

假设我在 table 中有我员工的数据,我想使用 JSON 通过 Web 服务检索它们。在这种情况下,我使用 ORDS、APEX 5.1.4 和 Oracle 12c

1.This 过程使用 APEX_JSON 检索 JSON 中的信息。我认为 APEX_JSON 在 Oracle 12c 中生成 JSON 相当不错,因为在 12c 中有很多与 JSON 相关的错误。

CREATE OR REPLACE PROCEDURE get_emp_json (p_empno IN emp.empno%TYPE DEFAULT NULL) AS
  l_cursor SYS_REFCURSOR;
BEGIN
  
  OPEN l_cursor FOR
    SELECT e.empno AS "empno",
           e.ename AS "employee_name",
           e.job AS "job",
           e.mgr AS "mgr",
           TO_CHAR(e.hiredate,'YYYY-MM-DD') AS "hiredate",
           e.sal AS "sal",
           e.comm  AS "comm",
           e.deptno AS "deptno"
    FROM   emp e
    WHERE  e.empno = DECODE(p_empno, NULL, e.empno, p_empno);

  APEX_JSON.open_object;
  APEX_JSON.write('employees', l_cursor);
  APEX_JSON.close_object;
END;
/

2.Build ORDS REST 模块(在您自己的架构中)

BEGIN
  ORDS.define_module(
    p_module_name    => 'rest-v4',
    p_base_path      => 'rest-v4/',
    p_items_per_page => 0);
  
  ORDS.define_template(
   p_module_name    => 'rest-v4',
   p_pattern        => 'employees/');

  ORDS.define_handler(
    p_module_name    => 'rest-v4',
    p_pattern        => 'employees/',
    p_method         => 'GET',
    p_source_type    => ORDS.source_type_plsql,
    p_source         => 'BEGIN get_emp_json; END;',
    p_items_per_page => 0);
    
  ORDS.define_template(
   p_module_name    => 'rest-v4',
   p_pattern        => 'employees/:empno');

  ORDS.define_handler(
    p_module_name    => 'rest-v4',
    p_pattern        => 'employees/:empno',
    p_method         => 'GET',
    p_source_type    => ORDS.source_type_plsql,
    p_source         => 'BEGIN get_emp_json(:empno); END;',
    p_items_per_page => 0);
    
  COMMIT;
END;
/

3.Call REST 网络服务

http://yourhost:yourport/ords/hr/rest-v4/employees/

结论

ORDS 是一个很棒的工具,可以使用 REST 创建 Web 服务,从数据库中检索 JSON 格式的数据。使其适应您自己的需要。通常集合可以派生自 table 或类型。在我的示例中,我使用 SYS_REFCURSOR 对象来检索 JSON 数据。

以下文章包含很好的示例和分步指南

https://oracle-base.com/articles/misc/oracle-rest-data-services-ords-create-basic-rest-web-services-using-plsql#create-get-web-services

https://oracle-base.com/articles/misc/oracle-rest-data-services-ords-restful-web-services-handling-complex-json-payloads

@RobertoHernandez 对 ORDS 服务进行了基本概述,这并不是我要搜索的内容,但谢谢!

  1. 填充集合并创建 JSON 对象的函数:
CREATE OR REPLACE FUNCTION f_get_data RETURN CLOB
AS
    cst_key CONSTANT VARCHAR(32) := 'KEY';
    cst_value CONSTANT VARCHAR(32) := 'VALUE';

    TYPE r_summary IS RECORD (
        key   VARCHAR2(255),
        value NUMBER
    ); 
    
    TYPE t_summary IS TABLE OF r_summary INDEX BY BINARY_INTEGER;
    
    r_s     r_summary;
    tab_s t_summary;

    json_clob CLOB;
 
    i INTEGER;   
BEGIN
    -- insert some dummy data to the collection
    FOR i IN 1..10 LOOP
        r_s.key := dbms_random.string('A', 10);
        r_s.value := ROUND(dbms_random.value(1,10), 2);
        
        tab_s(tab_s.COUNT + 1) := r_s;
    END LOOP;
    
    -- write data to a JSON object
    APEX_JSON.initialize_clob_output;
    APEX_JSON.open_object;
    
    APEX_JSON.open_array('data');
   
    IF tab_s.COUNT > 0 THEN
        FOR i IN tab_s.FIRST..tab_s.LAST LOOP
            IF tab_s.EXISTS(i) THEN
                APEX_JSON.open_object;
                APEX_JSON.write(cst_key, tab_s(i).key);
                APEX_JSON.write(cst_value, tab_s(i).value);
                APEX_JSON.close_object;
            END IF;
        END LOOP;
    END IF;
    
    APEX_JSON.close_all;
    
    json_clob := APEX_JSON.get_clob_output;
    APEX_JSON.free_output;
   
    RETURN json_clob;
END;
  1. 将 Web 服务创建为:
BEGIN
  ORDS.DEFINE_MODULE(
      p_module_name    => 'test',
      p_base_path      => '/data/',
      p_items_per_page =>  25,
      p_status         => 'PUBLISHED',
      p_comments       => NULL);  
  
  ORDS.DEFINE_TEMPLATE(
      p_module_name    => 'test',
      p_pattern        => 'all',
      p_priority       => 0,
      p_etag_type      => 'HASH',
      p_etag_query     => NULL,
      p_comments       => NULL);
  ORDS.DEFINE_HANDLER(
      p_module_name    => 'test',
      p_pattern        => 'all',
      p_method         => 'GET',
      p_source_type    => 'resource/lob',
      p_items_per_page =>  25,
      p_mimes_allowed  => '',
      p_comments       => NULL,
      p_source         => 
'SELECT
    ''application/json'',
    f_get_data
FROM
    sys.dual'
      );


  COMMIT; 
END;
  1. 最后调用 ORDS:
http://<host>:<port>/ords/<db>/<schema>/data/all/

有关更多详细信息,请阅读以下给了我想法的文章(@thatjeffsmith 的信条):

https://www.thatjeffsmith.com/archive/2017/09/ords-returning-raw-json/

当你想 return 一个 JSON 数组作为输出时,returning a refcursor 这种技术也适用于 autorest 情况参数.

您必须在模式或包级别声明记录和类型才能使其正常工作。

FUNCTION f_get_data
    RETURN SYS_REFCURSOR AS
    cst_key     CONSTANT VARCHAR(32) := 'KEY';
    cst_value   CONSTANT VARCHAR(32) := 'VALUE';


    r_s                  r_summary;
    tab_s                t_summary;

    json_clob            SYS_REFCURSOR;

    i                    INTEGER;
BEGIN
    -- insert some dummy data to the collection
    FOR i IN 1 .. 10
    LOOP
        r_s.key := DBMS_RANDOM.string('A', 10);
        r_s.VALUE := ROUND(DBMS_RANDOM.VALUE(1, 10), 2);

        tab_s(tab_s.COUNT + 1) := r_s;
    END LOOP;

    OPEN json_clob FOR SELECT * FROM TABLE(tab_s);

    RETURN json_clob;
END;