【问题标题】:Oracle Rest Data Service return a collection as JSONOracle Rest 数据服务以 JSON 形式返回集合
【发布时间】:2020-11-04 23:28:24
【问题描述】:

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

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

【问题讨论】:

  • 您的意思是 Oracle Rest 数据服务 (ORDS) 吗??
  • 是的,对不起.......
  • 集合存储在哪里?您可以将集合存储在一个类型中并将其作为 sys_refcursor 返回,然后您可以构建一个 ords 服务以使用 apex_json 将其收集为 json
  • 集合在函数中是本地的。我知道我可以创建一个模式级别的类型(集合和记录)然后从中选择,但我想在函数中本地解决它

标签: json oracle plsql oracle-ords


【解决方案1】:

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

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

1.此过程使用 APEX_JSON 检索 JSON 格式的信息。我认为 APEX_JSON 非常适合 Oracle 12c 中的 JSON 生成,因为在 12c 中有很多与 JSON 相关的 bug。

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.构建 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.调用 REST WEB SERVICE

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

结论

ORDS 是一个很棒的工具,可以使用 REST 从数据库中检索 JSON 格式的数据来创建 Web 服务。根据您自己的需要进行调整。通常,集合可以从表或类型派生。在我的示例中,我使用 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

【讨论】:

    【解决方案2】:

    @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/

    【讨论】:

      【解决方案3】:

      当您想要将 JSON 数组作为输出参数返回时,这种返回 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;
      

      【讨论】:

        猜你喜欢
        • 2018-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-14
        • 1970-01-01
        • 2021-09-08
        相关资源
        最近更新 更多