【问题标题】:white filter JSON with PHP使用 PHP 过滤 JSON
【发布时间】:2014-10-01 21:10:51
【问题描述】:

我从后端收到 API 响应,并希望通过 JS 将其转发给客户端(浏览器)。 但不应该有来自服务器的空洞响应。

一个 JSON 可能如下所示:

"{\"total\":6,\"sort\":{\"field\":\"created_at\",\"order\":\"desc\"},\"constraints\":       [],\"pagination\":  {\"current\":1,\"previous\":null,\"next\":null,\"per_page\":25,\"pages\":1,\"count\":6},\"response\":[{\"id\":10,\"name\":\"Prof. Dr. Dr. h. c.\",\"people_count\":2,\"allowed_actions\":{\"destroy\":false}},{\"id\":9,\"name\":\"Dr. h. c.\",\"people_count\":1,\"allowed_actions\":{\"destroy\":false}},{\"id\":8,\"name\":\"Dr. Dr.\",\"people_count\":0,\"allowed_actions\":{\"destroy\":true}},{\"id\":7,\"name\":\"Prof. Dr.\",\"people_count\":0,\"allowed_actions\":{\"destroy\":true}},{\"id\":6,\"name\":\"Prof.\",\"people_count\":4,\"allowed_actions\":{\"destroy\":false}},{\"id\":5,\"name\":\"Dr.\",\"people_count\":110,\"allowed_actions\":{\"destroy\":false}}],\"statuscode\":200}"

为了过滤它,我开始编写白名单。他以数组(“statuscode”,“response.name”,“response.id”,“total”)的形式获取洞json + 白名单。 现在他应该遍历这个 JSON 递归并返回一个具有相同结构但删除了所有其他节点的 json。

这是我目前的状态:

public function filter($response,$whitelist,$depth = 0) {
    $filteredResponse = "";

    foreach (json_decode($response,true) as $key => $value) {
        foreach ($whitelist as $item) {
            $items = explode(".",$item);
            foreach($items as $it) {
                if($it === $key && strlen($it)>0) {
                    if(is_array($value)) {
                        for($i=1;$i<count($items);$i++) {
                            $str .= $it.".";
                        }
                        $filteredResponse[$it] = $this->filter(json_encode($value),array($str),$depth+1);
                    }
                    else $filteredResponse[$key] = $value;
                }
            }

        }
    }
    return json_encode($filteredResponse);
}

我现在的结果是{"total":6,"response":"\"\"","statuscode":200}。 任何人都可以帮助我吗?

【问题讨论】:

  • 你的 JSON 是一个包含更多 JSON 的字符串?
  • 我得到了一个如上所示的字符串。使用 json_decode() 和 json_encode 我正在获取我的 json 或返回字符串。
  • @ÁlvaroG.Vicario 没有它的常规 json(Firefox 可以很好地解析它)
  • 我建议编写一个过滤器函数,该函数已经采用解码数组,并将结果重新编码为 json - 这样它只关心 php-array 而不是 JSON
  • @birdspider - 问题中显示的内容没有通过JSONLint,这就是我要问的原因。虽然它可能与问题无关:我认为这完全是关于如何循环深度嵌套的数组,而不是 JSON。

标签: php json filtering


【解决方案1】:

试试这个

<?php
$str = "{\"total\":6,\"sort\":{\"field\":\"created_at\",\"order\":\"desc\"},\"constraints\":       [],\"pagination\":  {\"current\":1,\"previous\":null,\"next\":null,\"per_page\":25,\"pages\":1,\"count\":6},\"response\":[{\"id\":10,\"name\":\"Prof. Dr. Dr. h. c.\",\"people_count\":2,\"allowed_actions\":{\"destroy\":false}},{\"id\":9,\"name\":\"Dr. h. c.\",\"people_count\":1,\"allowed_actions\":{\"destroy\":false}},{\"id\":8,\"name\":\"Dr. Dr.\",\"people_count\":0,\"allowed_actions\":{\"destroy\":true}},{\"id\":7,\"name\":\"Prof. Dr.\",\"people_count\":0,\"allowed_actions\":{\"destroy\":true}},{\"id\":6,\"name\":\"Prof.\",\"people_count\":4,\"allowed_actions\":{\"destroy\":false}},{\"id\":5,\"name\":\"Dr.\",\"people_count\":110,\"allowed_actions\":{\"destroy\":false}}],\"statuscode\":200}";


$arr = json_decode($str, true);


$arr_new = array();
$arr_new['total'] = $arr['total'];
$arr_new['statuscode'] = $arr['statuscode'];

foreach($arr['response'] as $arr_response)
{
      $arr_new['response_id'][] = $arr_response['id'];
      $arr_new['response_name'][] = $arr_response['name'];
}

print_r($arr_new);
?> 

输出:

Array
(
    [total] => 6
    [statuscode] => 200
    [response_id] => Array
        (
            [0] => 10
            [1] => 9
            [2] => 8
            [3] => 7
            [4] => 6
            [5] => 5
        )

    [response_name] => Array
        (
            [0] => Prof. Dr. Dr. h. c.
            [1] => Dr. h. c.
            [2] => Dr. Dr.
            [3] => Prof. Dr.
            [4] => Prof.
            [5] => Dr.
        )

)

Demo

【讨论】:

  • 感谢您的快速帮助。但问题是,这个过滤器应该一般适用于这种形式的所有 JSON,每个白名单输入。所以我必须遍历我的输入并递归工作。那是我的大问题......我没有得到它的工作:(
  • 你想得到什么?
  • 例如我有上面的旧响应:pastebin.com/4e4XRmCV 而我的 whitefilter 是 array("statuscode","re​​sponse.id","re​​sponse.name") 我想要这个输出:@ 987654323@希望我的问题现在更清楚了吗?
  • 我现在又添加了一个答案试试
  • 遗憾的是这个问题更复杂...... :(
【解决方案2】:
<?php
$str = "{\"total\":6,\"sort\":{\"field\":\"created_at\",\"order\":\"desc\"},\"constraints\":       [],\"pagination\":  {\"current\":1,\"previous\":null,\"next\":null,\"per_page\":25,\"pages\":1,\"count\":6},\"response\":[{\"id\":10,\"name\":\"Prof. Dr. Dr. h. c.\",\"people_count\":2,\"allowed_actions\":{\"destroy\":false}},{\"id\":9,\"name\":\"Dr. h. c.\",\"people_count\":1,\"allowed_actions\":{\"destroy\":false}},{\"id\":8,\"name\":\"Dr. Dr.\",\"people_count\":0,\"allowed_actions\":{\"destroy\":true}},{\"id\":7,\"name\":\"Prof. Dr.\",\"people_count\":0,\"allowed_actions\":{\"destroy\":true}},{\"id\":6,\"name\":\"Prof.\",\"people_count\":4,\"allowed_actions\":{\"destroy\":false}},{\"id\":5,\"name\":\"Dr.\",\"people_count\":110,\"allowed_actions\":{\"destroy\":false}}],\"statuscode\":200}";


$arr = json_decode($str, true);


$arr_new = array();
$arr_new['total'] = $arr['total'];
$arr_new['statuscode'] = $arr['statuscode'];

foreach($arr['response'] as $arr_response)
{
      $arr_temp = array();
      $arr_temp['id'] = $arr_response['id'];
      $arr_temp['name'] = $arr_response['name'];
      $arr_new['response'][] = $arr_temp; 
}

print_r($arr_new);

echo json_encode($arr_new);
?>  

输出:

Array
(
    [total] => 6
    [statuscode] => 200
    [response] => Array
        (
            [0] => Array
                (
                    [id] => 10
                    [name] => Prof. Dr. Dr. h. c.
                )

            [1] => Array
                (
                    [id] => 9
                    [name] => Dr. h. c.
                )

            [2] => Array
                (
                    [id] => 8
                    [name] => Dr. Dr.
                )

            [3] => Array
                (
                    [id] => 7
                    [name] => Prof. Dr.
                )

            [4] => Array
                (
                    [id] => 6
                    [name] => Prof.
                )

            [5] => Array
                (
                    [id] => 5
                    [name] => Dr.
                )

        )

)

{"total":6,"statuscode":200,"response":[{"id":10,"name":"Prof. Dr. Dr. h. c."},{"id":9,"name":"Dr. h. c."},{"id":8,"name":"Dr. Dr."},{"id":7,"name":"Prof. Dr."},{"id":6,"name":"Prof."},{"id":5,"name":"Dr."}]}  

Demo

【讨论】:

  • 再次感谢。但我认为我的问题不够清楚。您的解决方案工作正常 - 但它是硬编码的。我需要一个函数调用,比如 filter($json,$whitelist,..) 和 $whitelist=["total","statuscode","re​​sponse.name","re​​sponse.id"];但它也应该适用于 ["sort","re​​sponse.name","re​​sponse.people_count"];或完全不同的 JSON。
  • 这就是为什么我用 foreach ($whitelist as $item) { $items = explode(".",$item); .... }
【解决方案3】:

这是一个工作版本,它解决了我的问题:

    public function filter($response,$whiteList,$depth = 0) {
    $filteredResponse = $response;

    foreach ($filteredResponse as $key => $value) {
        $isBlackListed = true;

        foreach ($whiteList as $whiteItem) {
            $whiteTokens = explode(".", $whiteItem);

            if($depth >= count($whiteTokens))
                continue;
            if($key !== $whiteTokens[$depth])
                continue;
            else {
                if(is_array($value)) {
                    $isBlackListed = false;

                    if(!$this->is_assoc($value)) {
                        $i = 0;
                        foreach($value as $element) {
                            $filteredResponse[$key][$i] = $this->filter($element, $whiteList, $depth+1);
                            $i++;
                        }
                    } else {
                        if(count($whiteTokens) != $depth+1)
                            $filteredResponse[$key] = $this->filter($value, $whiteList, $depth+1);
                    }
                } else {
                    $isBlackListed = false;
                }
            }
        }

        if($isBlackListed) 
            unset($filteredResponse[$key]);

        $isBlackListed = true;
    }
    return $filteredResponse;
}

private function is_assoc($array) {
    return (bool)count(array_filter(array_keys($array), 'is_string'));
}

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 2016-05-24
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 2023-04-09
    • 2017-06-05
    • 2019-05-03
    相关资源
    最近更新 更多