1

我正在尝试构建一个 JSON 以在 Oracle Database XE 18c 上使用 ORDS 作为 HTTP GET 的结果返回。使用 JSON_OBJECT 和类似函数,SELECT 似乎总是用引号包围生成的 JSON,并在对象中转义引号。例子:

CREATE TABLE test_cases (
    team VARCHAR2(3),
    response_time NUMBER
);

INSERT INTO test_cases (team, response_time) VALUES ('foo', 1);
INSERT INTO test_cases (team, response_time) VALUES ('foo', 2);
INSERT INTO test_cases (team, response_time) VALUES ('foo', 5);
INSERT INTO test_cases (team, response_time) VALUES ('bar', 5);
INSERT INTO test_cases (team, response_time) VALUES ('bar', 7);
INSERT INTO test_cases (team, response_time) VALUES ('bar', 9);
COMMIT;

BEGIN
  ORDS.define_module(
    p_module_name    => 'rest',
    p_base_path      => 'rest/',
    p_items_per_page => 0
  );

  ORDS.define_template(
    p_module_name    => 'rest',
    p_pattern        => 'stats/'
  );

  ORDS.define_handler(
    p_module_name    => 'rest',
    p_pattern        => 'stats/',
    p_method         => 'GET',
    p_source_type    => ORDS.source_type_query_one_row,
    p_source         => '
SELECT JSON_OBJECTAGG (
    KEY t.team VALUE AVG(t.response_time)
)
AS averages
FROM test_cases t 
GROUP BY t.team 
                        ',
    p_items_per_page => 0
  );

  COMMIT;
END;
/

请求资源会给出以下结果:

$ curl -i -H "Content-Type: application/json" -X GET "http://localhost:8080/ords/rest/stats/"
HTTP/1.1 200 OK
Content-Type: application/json
{"averages":"{\"foo\":2.66666666666666666666666666666666666667,\"bar\":7}"}

其中引用了“平均值”的 JSON 值。该行为似乎是 JSON_OBJECT 特有的,因为使用相同 ORDS 参数的其他 SELECT 调用不会在结果中添加引号。

有没有办法在将 JSON_OBJECT 的输出构建到 SELECT 的结果之前对其进行去字符串化?

4

1 回答 1

3

由于您自己生成 JSON,因此您希望将 SOURCE_TYPE 更改为媒体资源。然后在您的查询中,第一列将是您的 mime 类型,以便您的浏览器知道如何处理传入的二进制数据。

尝试这个 -

BEGIN
  ORDS.DEFINE_HANDLER(
      p_module_name    => 'rest',
      p_pattern        => 'stats/',
      p_method         => 'GET',
      p_source_type    => 'resource/lob',
      p_items_per_page =>  0,
      p_mimes_allowed  => '',
      p_comments       => NULL,
      p_source         => 
'SELECT ''application/json'', JSON_OBJECTAGG (
    KEY t.team VALUE AVG(t.response_time)
)
AS averages
FROM test_cases t 
GROUP BY t.team '
      );

  COMMIT; 
END;
/

然后我在浏览器中进行 GET 调用 -

在此处输入图像描述

{
"foo": 2.6666666666666665,
"bar": 7
}

现在,假设您也有一些常规数据,但只有一列是 JSON 存储在 DB 中或由 DB 生成 - 您希望 ORDS 对常规数据进行 JSON 化,而不是已经是 json 的数据。

有一种方法可以让你的蛋糕也吃起来,放在银汤匙上。

BEGIN
  ORDS.DEFINE_HANDLER(
      p_module_name    => 'rest',
      p_pattern        => 'stats/',
      p_method         => 'GET',
      p_source_type    => 'json/collection',
      p_items_per_page =>  0,
      p_mimes_allowed  => '',
      p_comments       => NULL,
      p_source         => 
'SELECT JSON_OBJECTAGG (
    KEY t.team VALUE AVG(t.response_time)
)
"{}jsons"
FROM test_cases t 
GROUP BY t.team '
      );

  COMMIT; 
END;
/

对于您的 JSON 数据,添加此列别名

"{}jsons"

现在运行它看起来像这样 -

在此处输入图像描述

于 2020-02-27T00:33:18.837 回答