74136


PHP7.4を使用しています。

様々なAPIでJSON形式のレスポンスを受け取ったときに、戻り値をログに残すのですが、値によっては個人情報が含まれるため  
「数値または文字列の値の場合は、その値をマスキングする」  
ということをやりたいと思っています。  
（今回は、頭文字3文字だけを残してトリミングするという要件になっている。）

戻り値は半角英数字のほか、マルチバイト文字も含まれます。  
その為、トリミングの部分についてだけ言えば、JSONを配列に変換した上で、  
下記のような感じで処理はできるかなと思っています。

[code]

    function mask($array)
    {
        $res = [];
        foreach($array as $key => $val){
            $res[$key] = mb_substr($val,0,3);
        }
        return $res;
    }
    
[/code]

ただ問題なのが、APIの戻り値はAPIによって様々で、階層の深さもキー名も異なるため、どのようにして一律処理ができるかと悩んでいます。

APIの戻り値は例えばこのような内容です。

**戻り値:例1**

[code]

    {
        "Response":{
            "status":"1",
            "results":{
                "total":"1",
                "contents":[
                    {"postal":"0930000"}
                ]
            }
        }
    }
    
[/code]

**戻り値:例2**

[code]

    {
        "Response": {
            "order_info":[
                {
                    "order_id":"111111111",
                    "product_cd":"01234678901",
                    "product_name":"テスト商品名1",
                    "order_date":"2021-02-05"
                },
                {
                    "order_id":"111111112",
                    "product_cd":"01234678902",
                    "product_name":"テスト商品名2",
                    "order_date":"2021-02-05"
                },
                {
                    "order_id":"111111113",
                    "product_cd":"01234678903",
                    "product_name":"テスト商品名3",
                    "order_date":"2021-02-05"
                }
            ]
        }
    }
    
[/code]

このような戻り値で、階層やキー名がものによって異なる状況でも、  
配列やオブジェクトではない、数値や文字列の値に対して、  
前述のようなマスキング（トリミング）の操作を行う方法はあるでしょうか？

例として挙げた2つの戻り値でいえば、

[code]

    postal, customer_id, product_cd, product_name, order_date
    
[/code]

に対してだけ文字列操作を行うイメージです。  
（status, total も文字列ではあるので、それらに対して一律処理が走ってしまっても構いません）

トリミング後の結果としては、  
**例1**

[code]

    {
        "Response":{
            "status":"1",
            "results":{
                "total":"1",
                "contents":[
                    {"postal":"093"}
                ]
            }
        }
    }
    
[/code]

**例2**

[code]

    {
        "Response": {
            "order_info":[
                {
                    "order_id":"111",
                    "product_cd":"012",
                    "product_name":"テスト",
                    "order_date":"202"
                },
                {
                    "order_id":"111",
                    "product_cd":"012",
                    "product_name":"テスト",
                    "order_date":"202"
                },
                {
                    "order_id":"111",
                    "product_cd":"012",
                    "product_name":"テスト",
                    "order_date":"202"
                }
            ]
        }
    }
    
[/code]

のようになっていて欲しいのです。  
（ログに書き込む際にユニークなIDを別途振っているので、トリミングによって例えばorder_info以下の値が重複しているように見える・一意ではなくなることについては問題ありません。）

JSONは都度、連想配列などに変換してしまってよいので、  
すみませんがどなたか、お知恵を拝借できましたら大変助かります・・・mm


CC BY-SA 4.0
2021-02-19T10:30:12.303
74135
2021-02-19T11:34:29.823
2021-02-19T11:34:29.823
3060
43186
question
php json array
PHPの多次元配列で、階層の深さやキー名が毎回異なる場合に、数値または文字列の値のときだけ操作を行うにはどうしたらよいか


以下は [array_walk_recursive](https://www.php.net/manual/en/function.array-walk-
recursive.php) を使う方法です。

[code]

    <?php
    
    function mask(&$item, $key) {
      if (!is_string($item) || mb_strlen($item) <= 3) return;
      $item = mb_substr($item, 0, 3);
      return;
    }
    
    $arr = json_decode(file_get_contents('example1.json'), true);
    array_walk_recursive($arr, 'mask');
    $json = json_encode($arr, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);
    
    echo($json);
    
[/code]

`example1.json` の内容は「戻り値:例1」にある JSON 形式のテキストです。結果は以下の様になります。

[code]

    {
        "Response": {
            "status": "1",
            "results": {
                "total": "1",
                "contents": [
                    {
                        "postal": "093"
                    }
                ]
            }
        }
    }
    
[/code]

問題点としては `status` や `total` が 4 桁(文字)以上の場合に削られてしまう事です。`mask`
関数内で何らかの判定ルーチンを追加する必要があるでしょう。


CC BY-SA 4.0
2021-02-19T11:27:43.213
74136
2021-02-19T11:27:43.213
74135
answer