我正在寻找一种方法来创建/传递用于生成JSON文档的动态列列表.

创建以下内容(在Oracle 19c上):

CREATE TABLE tbl1 (val1 varchar2(10), val2 varchar2(10), val3 varchar2(10));
INSERT INTO tbl1 VALUES ('1','2','3');
INSERT INTO tbl1 VALUES ('a','b','c');
INSERT INTO tbl1 VALUES ('1','b','3');

该查询给出了我想要的输出,但是关于键和值部分中的列名(或val1、val2、val3)是静态的.

with qry as (
  select *
  from tbl1
)
select json_object(
'keys' : ['VAL1', 'VAL2', 'VAL3'],
'values' : json_arrayagg(json_array(val1, val2, val3 null on null))) as js
from qry
JS
{"keys":["VAL1","VAL2","VAL3"],"values":[["1","2","3"],["a","b","c"],["1","b","3"]]}

我正在寻找一种方法,将键和值部分替换为动态列表.这并不完全正确(仍然有静态值调用,键的每一端都被额外的"S"包围,但这是我所能实现的最接近的结果.寻求帮助以使其完全动态.理想情况下,能够更改WITH子句中的表并为其他表构建.

with qry as (
  select tbl1.*, 
  (select
  listagg ('''''' || column_name || '''''', ',') within group (order by column_name)
  from all_tab_cols
  where table_name = 'TBL1') as cols
  from tbl1
)
select json_object(
'keys' : [json_query(json_arrayagg(qry.cols), '$[0]') FORMAT JSON],
'values' : json_arrayagg(json_array(val1, val2, val3 null on null))) as js
from qry
JS
{"keys":["''VAL1'',''VAL2'',''VAL3''"],"values":[["1","2","3"],["1","b","3"],["a","b","c"]]}

fiddle

推荐答案

您可以创建帮助器函数:

CREATE FUNCTION object_to_array(
  value IN VARCHAR2
) RETURN VARCHAR2
IS
  js   JSON_OBJECT_T := JSON_OBJECT_T( value );
  arr  JSON_ARRAY_T := JSON_ARRAY_T();
  keys JSON_KEY_LIST := js.get_keys();
BEGIN
  FOR i in 1 .. keys.COUNT LOOP
    arr.append(js.get_string(keys(i)));
  END LOOP;
  RETURN arr.to_string();
END;
/

然后,您可以使用:

SELECT json_object(
         KEY 'keys' VALUE MIN(p.keys) FORMAT JSON,
         KEY 'values' VALUE JSON_ARRAYAGG(object_to_array(t.json) FORMAT JSON)
       ) as js
FROM   (SELECT JSON_OBJECT(*) AS json FROM tbl1) t
       CROSS JOIN LATERAL(
         SELECT JSON_DATAGUIDE(t.json) AS data FROM DUAL
       ) d
       CROSS JOIN LATERAL(
         SELECT JSON_ARRAYAGG(SUBSTR(path, 3)) AS keys
         FROM   JSON_TABLE(
                  d.data,
                  '$[*]'
                  COLUMNS(
                    path VARCHAR2(20) PATH '$."o:path"'
                  )
                )
         WHERE  path != '$'
       ) p

其中,对于样本数据:

CREATE TABLE tbl1 (val1 varchar2(10), val2 varchar2(10), val3 varchar2(10));

INSERT INTO tbl1 VALUES ('1','2','3');
INSERT INTO tbl1 VALUES ('a','b','c');
INSERT INTO tbl1 VALUES ('1','b','3');
INSERT INTO tbl1 VALUES ('2','d',NULL);

输出:

JS
{"keys":["VAL1","VAL2","VAL3"],"values":[["1","2","3"],["a","b","c"],["1","b","3"],["2","d",null]]}

Oracle 21 fiddle


或者,您可以创建两个助手函数:

CREATE FUNCTION object_keys_to_array(
  value IN VARCHAR2
) RETURN VARCHAR2
IS
  js   JSON_OBJECT_T := JSON_OBJECT_T( value );
  arr  JSON_ARRAY_T := JSON_ARRAY_T();
  keys JSON_KEY_LIST := js.get_keys();
BEGIN
  FOR i in 1 .. keys.COUNT LOOP
    arr.append(keys(i));
  END LOOP;
  RETURN arr.to_string();
END;
/

CREATE FUNCTION object_values_to_array(
  value IN VARCHAR2
) RETURN VARCHAR2
IS
  js   JSON_OBJECT_T := JSON_OBJECT_T( value );
  arr  JSON_ARRAY_T := JSON_ARRAY_T();
  keys JSON_KEY_LIST := js.get_keys();
BEGIN
  FOR i in 1 .. keys.COUNT LOOP
    arr.append(js.get_string(keys(i)));
  END LOOP;
  RETURN arr.to_string();
END;
/

然后,您可以使用:

SELECT json_object(
         KEY 'keys' VALUE MIN(object_keys_to_array(json)) FORMAT JSON,
         KEY 'values' VALUE JSON_ARRAYAGG(object_values_to_array(json) FORMAT JSON)
       ) as js
FROM   (SELECT JSON_OBJECT(*) AS json FROM tbl1)

它的输出是相同的.

Oracle 21 fiddle


@Astentx comments 建议使用不带助手函数的方法:

SELECT JSON_OBJECT(
         KEY 'keys' VALUE MIN(p.keys) FORMAT JSON,
         KEY 'values' VALUE JSON_ARRAYAGG(
           JSON_QUERY(
             t.json FORMAT JSON,
             '$.*'
             WITH UNCONDITIONAL ARRAY WRAPPER
           ) FORMAT JSON
         )
       ) as js
FROM   (SELECT JSON_OBJECT(*) AS json FROM tbl1) t
       CROSS JOIN LATERAL(
         SELECT JSON_DATAGUIDE(t.json) AS data FROM DUAL
       ) d
       CROSS JOIN LATERAL(
         SELECT JSON_ARRAYAGG(SUBSTR(path, 3)) AS keys
         FROM   JSON_TABLE(
                  d.data,
                  '$[*]'
                  COLUMNS(
                    path VARCHAR2(20) PATH '$."o:path"'
                  )
                )
         WHERE  path != '$'
       ) p

它的输出也是一样的.

Oracle 21 fiddle

Json相关问答推荐

Jolt转换问题—使用键查找匹配对象

删除JSON文件的特定内容

如何在数组抖动中按值分组

如何在Swift中使用JSON编码器的泛型

419(未知状态)使用laravel处理PUT请求

如何使用jq使用子值对象的键对json对象进行分组

震动范围改善

Golang jsonrpc2 服务器在哪里监听?

如何将复杂的 JSON 反序列化为 Rust 类型?

使用 jq 将消息转换为数组

在 JOLT 中重新排列值

通过一个序列化器更新多个模型数据

使用带有逗号的字段名称构建 struct

使用 Jolt 变换将平面 json 转换为具有多个数组的嵌套 Json

为什么在测试 RSPEC 时 JBuilder 不返回 JSON 中的响应正文

jquery用json数据填充下拉列表

如何使用 Jackson 注释从 HttpResponse 反序列化 JSON 对象?

waitUntilAllTask​​sAreFinished 错误 Swift

如何在spark 上将json字符串转换为数据帧

通过url获取json数据并在python中使用(simplejson)