我正在Oracle 19 c中编写一个函数,它应该在给定的json_select_t上循环所有键(可以具有任何 struct ),如果键是预先指定的键之一,则用星号屏蔽值.这些值是卡号.然后,该函数应该返回更改后的json_body_t.

我的问题是返回的json没有变化.

这是我的代码.输入json只是一个例子;它应该与任何json一起工作.目前的代码写为pi/SQL块:

DECLARE
  v_output CLOB;
  v_input_json JSON_OBJECT_T;
  v_json_object JSON_OBJECT_T;
  PROCEDURE mask_keys(p_json IN OUT NOCOPY JSON_OBJECT_T)
  IS
    v_keys JSON_KEY_LIST;
    v_key VARCHAR2(100);
    v_value JSON_ELEMENT_T;
    v_json_array JSON_ARRAY_T := JSON_ARRAY_T();
    v_index NUMBER;
    TYPE param_values_t IS TABLE OF VARCHAR2(100); 
    v_param_values param_values_t := param_values_t('CardNum', 'CardNumber', 'acctNum', 'acctNumber'); --keys to mask
    
    FUNCTION mask_numeric_value(p_value VARCHAR2) RETURN VARCHAR2 IS --function to mask the value
        v_masked_value VARCHAR2(100);
        v_value varchar2(100) := p_value;
    BEGIN
    dbms_output.put_line('function mask_numeric_value - start'); 
    v_value := trim(BOTH '"' from v_value);
        IF REGEXP_LIKE(v_value, '^\d+$') THEN
            v_masked_value := SUBSTR(v_value, 1, 6) || '******' || SUBSTR(v_value, -4);
        ELSE
            v_masked_value := v_value;
        END IF;
        RETURN v_masked_value;
    END mask_numeric_value;
  BEGIN
    DBMS_OUTPUT.PUT_LINE('function mask_keys - start');
       v_keys := p_json.get_keys;
        FOR i IN 1..v_keys.count LOOP
          v_key := v_keys(i);
          v_value := p_json.get(v_key);
          DBMS_OUTPUT.PUT_LINE('Key: ' || v_key || ', Value: ' || v_value.to_string);
          IF v_key MEMBER OF v_param_values THEN
          dbms_output.put_line('Found'); 
            IF v_value.is_string THEN
             dbms_output.put_line('Masking'); 
             p_json.put(v_key, mask_numeric_value(v_value.to_string()));
             DBMS_OUTPUT.PUT_LINE('New value: '||p_json.get(v_key).to_string);
            END IF;
          ELSIF v_value.is_object THEN
          DBMS_OUTPUT.PUT_LINE('Value is an object');
          DBMS_OUTPUT.PUT_LINE(v_value.to_string);
          v_json_object := JSON_OBJECT_T.parse(v_value.to_string());
          -- If the element is an object, recursively call mask_keys
          mask_keys(v_json_object);
          ELSIF v_value.is_array THEN
            DBMS_OUTPUT.PUT_LINE('Value is an array');
            v_json_array := JSON_ARRAY_T.parse(v_value.to_string());
            FOR j IN 0..v_json_array.get_size() - 1 LOOP
                -- If the array element is an object, recursively call mask_keys
                IF v_json_array.get(j).is_object THEN
                    DBMS_OUTPUT.PUT_LINE('Element is an object');
                    v_json_object := JSON_OBJECT_T.parse(v_json_array.get(j).to_string());
                    mask_keys(v_json_object);
                END IF;
            END LOOP;
            END IF;
        END LOOP;
  END mask_keys;

BEGIN
    v_input_json := JSON_OBJECT_T.parse('{
        "success": true,
        "payload": {
            "authSumCnt": "1",
            "CardNum": "7712343649057813",
            "authSum": [
                {
                    "CardNumber": "9512343649057813",
                    "otherKey": "otherValue"
                },
                {
                    "acctNum": "1234567890123456",
                    "anotherKey": "anotherValue",
                    "nestedArray": [
                        {
                            "nestedKey": "nestedValue",
                            "acctNumber": "1234567890123456"
                        }
                    ]
                }
            ]
        }
    }');
    
    mask_keys(v_input_json);
    v_output := v_input_json.to_clob;
    DBMS_OUTPUT.PUT_LINE(v_output);
END;

返回v_put与输入相同:

  {
        "success": true,
        "payload": {
            "authSumCnt": "1",
            "CardNum": "7712343649057813",
            "authSum": [
                {
                    "CardNumber": "9512343649057813",
                    "otherKey": "otherValue"
                },
                {
                    "acctNum": "1234567890123456",
                    "anotherKey": "anotherValue",
                    "nestedArray": [
                        {
                            "nestedKey": "nestedValue",
                            "acctNumber": "1234567890123456"
                        }
                    ]
                }
            ]
        }
    }

推荐答案

问题在于,您正在将字符串值解析为新的SON对象,而这些对象则独立于原始的输入参数.

所以,而不是:

            v_json_object := JSON_OBJECT_T.parse(v_value.to_string());

只需获取实际对象:

            v_json_object := p_json.get_object(v_key);

而不是:

            v_json_array := JSON_ARRAY_T.parse(v_value.to_string());
...
                v_json_object := JSON_OBJECT_T.parse(v_json_array.get(j).to_string());

获取原始数组及其元素,作为对象:

            v_json_array := p_json.get_array(v_key);
...
                v_json_object := new JSON_OBJECT_T(v_json_array.get(j));

所以全文:

DECLARE
  v_output CLOB;
  v_input_json JSON_OBJECT_T;
  v_json_object JSON_OBJECT_T;

  PROCEDURE mask_keys(p_json IN OUT NOCOPY JSON_OBJECT_T)
  IS
    v_keys JSON_KEY_LIST;
    v_key VARCHAR2(100);
    v_value JSON_ELEMENT_T;
    v_json_array JSON_ARRAY_T := JSON_ARRAY_T();
    v_index NUMBER;
    TYPE param_values_t IS TABLE OF VARCHAR2(100); 
    v_param_values param_values_t := param_values_t('CardNum', 'CardNumber', 'acctNum', 'acctNumber'); --keys to mask

    FUNCTION mask_numeric_value(p_value VARCHAR2) RETURN VARCHAR2 IS --function to mask the value
        v_masked_value VARCHAR2(100);
        v_value varchar2(100) := p_value;
    BEGIN
    dbms_output.put_line('function mask_numeric_value - start'); 
    v_value := trim(BOTH '"' from v_value);
        IF REGEXP_LIKE(v_value, '^\d+$') THEN
            v_masked_value := SUBSTR(v_value, 1, 6) || '******' || SUBSTR(v_value, -4);
        ELSE
            v_masked_value := v_value;
        END IF;
        RETURN v_masked_value;
    END mask_numeric_value;
  BEGIN
    DBMS_OUTPUT.PUT_LINE('function mask_keys - start');
      v_keys := p_json.get_keys;
        FOR i IN 1..v_keys.count LOOP
          v_key := v_keys(i);
          v_value := p_json.get(v_key);
          DBMS_OUTPUT.PUT_LINE('Key: ' || v_key || ', Value: ' || v_value.to_string);
          IF v_key MEMBER OF v_param_values THEN
            dbms_output.put_line('Found'); 
            IF v_value.is_string THEN
              dbms_output.put_line('Masking'); 
              p_json.put(v_key, mask_numeric_value(v_value.to_string()));
              DBMS_OUTPUT.PUT_LINE('New value: '||p_json.get(v_key).to_string);
            END IF;
          ELSIF v_value.is_object THEN
            DBMS_OUTPUT.PUT_LINE('Value is an object');
            DBMS_OUTPUT.PUT_LINE(v_value.to_string);
/*
            v_json_object := JSON_OBJECT_T.parse(v_value.to_string());
*/
            -- If the element is an object, recursively call mask_keys
            v_json_object := p_json.get_object(v_key);
            mask_keys(v_json_object);
          ELSIF v_value.is_array THEN
            DBMS_OUTPUT.PUT_LINE('Value is an array');
/*
            v_json_array := JSON_ARRAY_T.parse(v_value.to_string());
*/
            v_json_array := p_json.get_array(v_key);
            FOR j IN 0..v_json_array.get_size() - 1 LOOP
              -- If the array element is an object, recursively call mask_keys
              IF v_json_array.get(j).is_object THEN
                DBMS_OUTPUT.PUT_LINE('Element is an object');
/*
                v_json_object := JSON_OBJECT_T.parse(v_json_array.get(j).to_string());
*/
                v_json_object := new JSON_OBJECT_T(v_json_array.get(j));
                mask_keys(v_json_object);
              END IF;
            END LOOP;
          END IF;
        END LOOP;
  END mask_keys;

BEGIN
    v_input_json := JSON_OBJECT_T.parse('{
        "success": true,
        "payload": {
            "authSumCnt": "1",
            "CardNum": "7712343649057813",
            "authSum": [
                {
                    "CardNumber": "9512343649057813",
                    "otherKey": "otherValue"
                },
                {
                    "acctNum": "1234567890123456",
                    "anotherKey": "anotherValue",
                    "nestedArray": [
                        {
                            "nestedKey": "nestedValue",
                            "acctNumber": "1234567890123456"
                        }
                    ]
                }
            ]
        }
    }');

    mask_keys(v_input_json);
    v_output := v_input_json.to_clob;
    DBMS_OUTPUT.PUT_LINE(v_output);
END;
/

它产生(格式化):

{
  "success": true,
  "payload": {
    "authSumCnt": "1",
    "authSum": [
      {
        "otherKey": "otherValue",
        "CardNumber": "951234******7813"
      },
      {
        "anotherKey": "anotherValue",
        "nestedArray": [
          {
            "nestedKey": "nestedValue",
            "acctNumber": "123456******3456"
          }
        ],
        "acctNum": "123456******3456"
      }
    ],
    "CardNum": "771234******7813"
  }
}

fiddle

Json相关问答推荐

基于两个条件替换扁平化的SON中的值

如何在JMESPath中区分空和假?

删除JSON文件的特定内容

Bash和echo命令出现意外结果

使用json_query更新事实

如何在改装Android中将ResponseBody转换为JSONObject

如何在Android中解析带有动态键和可变对象名称的改装JSON响应?

报告重复的对象键

如何在 jq 中按 IP 地址排序?

将请求中的数据推送到数组中

父键中的 Perl JSON 数组

如何用 Xidel 正确读取这个 JSON 文件?

使用 @ResponseBody 自定义 HttpMessageConverter 来做 Json 事情

如何在返回对象的 Spring MVC @RestController @ResponseBody 类中响应 HTTP 状态代码?

Spring MVC控制器中的JSON参数

在 Rails 3 中处理 JS/ERB 模板中的 JSON

在android中读取Json数组

NSURLRequest 中不支持的 URL

XML vs YAML vs JSON

如何从 jQuery ajax 调用将复杂对象传递给 ASP.NET WebApi GET?