在 Oracle PL/SQL 中从 table 生成 json 文件

Generating json file from table in Oracle PL/SQL

我在 table 中有以下表格的数据。

我想生成以下格式的数据。

{
    "delete": [
        {
            "canonicalName": "TCS"          
        }
    ],
    "update": [
         {
            "canonicalName": "Wipro tech"
            "synonyms": [
                "Wipro technology"
            ]
         },
         {
            "canonicalName": "Infosys"
            "synonyms": [
                "Infosys tech"
            ]
         }
    ]       
    "add": [
        {
            "canonicalName": "Apple Computers",
            "synonyms": [
                "Apple"
            ]
        },
        {
            "canonicalName": "Google India",
            "synonyms": ["Google"]
        }
    ]
}

我可以使用一些库和 POJO class 在 java 中编写相同的内容。有没有可能我可以在 Oracle PL/SQL 中创建?早些时候我从 jdbc 读取数据并用 java 代码创建这个文件。现在我必须将此代码保留为 pl/sql 过程的一部分。无论如何我可以生成上述格式的数据吗?

如果您的数据库版本是 12cR2+,那么您可以将 json_objectagg()json_object()json_array() 函数一起使用,如

SELECT json_query(
       json_objectagg
                 ( operation VALUE 
                   json_array(json_object('canonicalName' VALUE orgname,
                                          'synonyms'      VALUE json_array(synonyms) ) ) ),
       '$' returning VARCHAR2(4000) pretty )
    AS "Result JSON" 
  FROM tab

不要忘记添加 json_query( ... , '$' returning VARCHAR2(4000) pretty ) 包裹整个表达式以获得漂亮的外观。

Demo

在您的输出中,当一个组织只有一个规范名称(没有同义词)时,您只显示一个 属性 规范名称的相应对象。如果您允许 "synonyms" 属性 在所有情况下都存在会更容易 - 相应的数组可以为空 - 但这不是您在所需输出中显示的内容。

如果您允许空数组作为 "synonyms" 的值,那么 Barbaros Ozhan 已经提供了解决方案。 编辑 经检查,这可能不完全正确;该解决方案不会将单个组织的同义词聚合到一个数组中(具有两个或更多同义词),而是将它们显示为不同的对象。请参阅下面我添加到答案中的示例数据。 结束编辑

此处进行大量编辑 我正在添加示例数据以进行测试。我假设如果一个组织有两个或更多同义词(在同一个操作下),那应该导致操作数组的单个成员(规范名称只出现一次,带有两个或更多同义词的数组)。

我也修改了我的解决方案 - 找到了更简单的方法。单击答案下方的“已编辑”link 可以看到对解决方案的更改。

测试数据:

drop table t purge;
create table t (orgname, synonyms, operation) as
  select 'Apple Computers', 'Apple'           , 'add'    from dual union all
  select 'Apple Computers', 'Apple Inc'       , 'add'    from dual union all
  select 'Google India'   , 'Google'          , 'add'    from dual union all
  select 'Wipro Tech'     , 'Wipro Technology', 'update' from dual union all
  select 'Infosys'        , 'Infosys Tech'    , 'update' from dual union all
  select 'TCS'            , null              , 'delete' from dual union all
  select 'IBM'            , null              , 'delete' from dual union all
  select 'IBM'            , 'IBM Corporation' , 'delete' from dual union all
  select 'IBM'            , 'IBM Corporation' , 'add'    from dual
;

查询:

with
  prep (operation, orgname, fragment) as (
    select operation, orgname,
           json_object( key 'canonicalName' value orgname,
                        key 'synonyms'
              value nullif(json_arrayagg(synonyms order by synonyms), '[]')
                                  FORMAT JSON  ABSENT ON NULL
                      )
     from   t
     group  by orgname, operation
   )
select json_objectagg( key operation
                       value json_arrayagg(fragment order by orgname)
                     ) as json_str
from   prep
group  by operation
;

输出(漂亮的打印):

{
  "add" :
  [
    {
      "canonicalName" : "Apple Computers",
      "synonyms" :
      [
    "Apple",
    "Apple Inc"
      ]
    },
    {
      "canonicalName" : "Google India",
      "synonyms" :
      [
    "Google"
      ]
    },
    {
      "canonicalName" : "IBM",
      "synonyms" :
      [
    "IBM Corporation"
      ]
    }
  ],
  "delete" :
  [
    {
      "canonicalName" : "IBM",
      "synonyms" :
      [
    "IBM Corporation"
      ]
    },
    {
      "canonicalName" : "TCS"
    }
  ],
  "update" :
  [
    {
      "canonicalName" : "Infosys",
      "synonyms" :
      [
    "Infosys Tech"
      ]
    },
    {
      "canonicalName" : "Wipro Tech",
      "synonyms" :
      [
    "Wipro Technology"
      ]
    }
  ]
}