Oracle 12c:从JSON数组中删除JSON对象

oxf4rvwz  于 2023-01-18  发布在  Oracle
关注(0)|答案(3)|浏览(226)

我需要创建一个接受CLOB输入的函数,并且需要删除与条件匹配的数组。

create or replace FUNCTION remove_config_node_by_key (
    p_in_json   IN   CLOB,
    p_in_key    IN   VARCHAR2
) RETURN CLOB IS
    l_ja   json_array_t;
    l_po   json_object_t;
    l_key  VARCHAR2(500);
BEGIN
    l_ja := json_array_t.parse(p_in_json);
    FOR idx IN 0.. l_ja.get_size - 1 LOOP
        l_po := json_object_t(l_ja.get(idx));
        l_key := l_po.get_string('key');
        -- check if the key matches with input and then delete that node.
        dbms_output.put('Key to remove in the JSON: ' || l_key);
        IF l_key = p_in_key THEN
            dbms_output.put('Key to remove in the JSON: ' || l_key);
           l_ja.remove (idx);
         --   dbms_output.new_line;
           dbms_output.put('Key is removed in the JSON: ' || l_key);
        END IF;

    END LOOP;

    RETURN l_ja.to_clob;
END;

调用时使用:

update COLD_DRINKS cd set cd.configuration = remove_config_node_by_key(cd.configuration, 'b') 
where country='INDIA';

我得到错误:

Error report -
ORA-30625: method dispatch on NULL SELF argument is disallowed
ORA-06512: at "SYS.JSON_OBJECT_T", line 72
ORA-06512: at "PLATFORM_ADMIN_DATA.REMOVE_CONFIG_NODE_BY_KEY", line 11

输入JSON:

[
    {
        "key": "a",
        "value": "lemon soda"
    },
    {
        "key": "b",
        "value": "Coke"
    },
    {
        "key": "c",
        "value": "Pepsi"
    }
    
]

执行后预期JSON:

[
    {
        "key": "a",
        "value": "lemon soda"
    },
    {
        "key": "c",
        "value": "Pepsi"
    }
    
]

我认为这个l_ja.remove(idx)有问题;因为此操作导致异常。无法移除索引处的对象。

lymnna71

lymnna711#

在18c中,至少it works with your sample data(从数组中删除末尾的逗号),但是it gets that error with a null configuration
因此,您可以在函数中测试null,或者从更新中排除null,或者修复数据使其不包含null。
最简单的方法可能是添加一个空检查:

...
BEGIN
    IF p_in_json IS NULL THEN
        RETURN NULL;
    END IF;
    l_ja := json_array_t.parse(p_in_json);
...

fiddle

yx2lnoni

yx2lnoni2#

您也可以使用json_transform删除它:

create or replace function remove_config_node_by_key (
    p_in_json   IN   CLOB,
    p_in_key    IN   VARCHAR2
) RETURN CLOB IS
    l_result CLOB ;
begin
    execute immediate q'~select json_transform(
        :p_in_json,
        REMOVE '$[*]?(@.key == "~' || p_in_key || q'~")'
     )
     from dual~' into l_result using p_in_json  
     ;
     return l_result ;
end ;
/

(with有关可能的SQL注入的所有常见注解...)

ncgqoxb0

ncgqoxb03#

在for循环中添加REVERSE后,问题得到解决
之前[错误]

FOR idx IN 0.. l_ja.get_size - 1

[通过]后

FOR idx IN REVERSE 0.. l_ja.get_size - 1

完整的工作功能

CREATE OR REPLACE FUNCTION remove_config_node_by_key (
    p_in_json   IN   CLOB,
    p_in_key    IN   VARCHAR2
) RETURN CLOB IS
    l_ja   json_array_t := json_array_t ();
    l_po   json_object_t;
    l_key  VARCHAR2(500);
BEGIN
    l_ja := json_array_t.parse(p_in_json);
    FOR idx IN REVERSE 0.. l_ja.get_size - 1 
    LOOP
        l_po := json_object_t(l_ja.get(idx));
        l_key := l_po.get_string('key');
        -- check if the key matches with input and then delete that node.
        IF l_key = p_in_key THEN
            dbms_output.put_line('Key to remove in the JSON: ' || l_key || ' at index : ' || idx);
            l_ja.remove (idx);
           dbms_output.put_line('Key is removed in the JSON: ' || l_key);
        END IF;
    END LOOP;

    RETURN l_ja.to_clob;
END;
/

相关问题