【问题标题】:See if value exists in deep nested json array查看值是否存在于深层嵌套的 json 数组中
【发布时间】:2019-10-25 00:41:55
【问题描述】:

这里有我的简单 json 响应:

Array
(
    [data] => Array
        (
            [id] => 3
            [type] => workspace
            [attributes] => Array
                (
                    [name] => testing
                    [slug] => testing
                    [data] =>
                    [created_at] => 
                    [updated_at] => 
                    [role] => Amazing
                    [last_accessed_at] =>
                )

        )

)

是否可以创建一个通用函数来简单地在给定路径中查找给定值?

例如,我想做一个函数,用给定的键递归搜索给定的值:

public function seeIfValueExistsInJson("data.attributes.slug", "testing"){

}

我想让它尽可能通用,以包含响应的第一项不是“数据”并且可能是其他内容。

有没有人看到/制作过类似的东西并愿意分享?

谢谢你:)


更新: 我在技术上设法做到了这一点。但我知道这不是最好的方法,因为它感觉或看起来不像,我很乐意看到您对如何改进它以帮助我进一步改进我的代码的批评:

public function extractData($fullPath, $value)
    {

        $jsonString = json_encode($this->json());
        $paths = explode(".", $fullPath);
        $oldPos = 0;
        $len = sizeof($paths) - 1;
        foreach ($paths as $path) {
            if (strpos($jsonString, $path) !== false) {
                $currPos = strpos($jsonString, $path);
                if ($currPos > $oldPos) {
                    if ($len === 0) {
                        $valuePos = strpos($jsonString, $value);
                        PHPUnit::assertTrue($currPos < $valuePos);
                        break;
                    }
                    $len--;
                }
                $oldPos = $currPos;
            } else {
                print("The path: '$path' is not within this Json response");
            }
        }
    }

如您所见,此函数将给定的响应 json 转换为字符串,并获取您给它的每个“路径”索引的位置(在分解它们之后),然后确保索引的先前位置更小比下一个(这意味着你要寻找的下一个索引路径必须在之后),然后一旦它到达循环的末尾,它将(在我的情况下使用 phpunit)断言你给出的值是更远的沿着列表比最后一个索引路径。就响应中的相同字符串等而言,这似乎确实有很多缺陷。所以我欢迎任何关于如何改进这一点的反馈

【问题讨论】:

  • 您好,您能补充一下您目前尝试过的内容吗? Stackoverflow 不是免费的编码服务。请尝试自己解决您的问题,然后返回有关实际代码的问题。谢谢。
  • Find a key in nested json的可能重复
  • 由于 JSON 只是一个字符串,您可以查看 JSON 字符串是否包含您想要的值,如果包含,则从那里执行任何逻辑...
  • 是的,当然,抱歉。我尝试手动创建自己的函数来查找第一个数组是否与给定的相同,如果是则继续下一个但被卡住并且无法继续。尝试使用不同 array_ 函数的组合无济于事
  • @TobyR 您绝对应该添加您尝试过的其他代码,以及您的尝试出错的原因:包括它们给出的错误消息或它们的输出如何偏离您想要的结果。

标签: php arrays


【解决方案1】:

由于您已经有一个数组,您可以分解$fullPath 并搜索该数组中的每个键。如果没有这样的密钥,返回false。否则,检查路径的值是否等于$value

$arr = ['data' => ['id' => 3, 'type' => 'workspace',
        'attributes' => ['name'=>'testing', 'slug'=>'testing', 
                         'data' => '', 'created_at' =>'',
                         'updated_at' => '', 'role' => 'Amazing',
                         'last_accessed_at' => '']]];

function seeIfValueExistsInJson($arr, $fullPath, $value){
    $tempArr = $arr;
    $keys = explode('.', $fullPath);
    foreach($keys as $key){
      if(isset($tempArr[$key])){
          $tempArr = $tempArr[$key];
      }
      else return false;
    }
    return $tempArr === $value;
}

$result = seeIfValueExistsInJson($arr, "data.attributes.slug", "testing");
echo 'Result: ' . $result;

这将返回:

Result: 1 

【讨论】:

    【解决方案2】:

    我强烈建议反对将字符串编码为 JSON,然后搜索 JSON。这种策略在一般意义上是行不通的。您需要遍历数据结构,可能使用某种递归函数。 (我不会在这里写。)

    如果数据以 JSON 形式出现,则应首先将其解码为数据结构。 (将 JSON 字符串视为“黑匣子”。)

    【讨论】:

    • 我知道您强烈建议不要这样做,因为这显然存在很多缺陷和问题。这就是为什么我试图找到另一种方式:/
    【解决方案3】:

    您可以使用array_walk_recursive PHP 函数。

    <?php
    $data = json_decode($json);
    $hasData = false;
    $searchString = "";
    array_walk_recursive($data, function($value, $key) {
        $hasData = $hasData || $value == $searchString;
    });
    

    PS.:您可能需要为类型检查添加一些调整。 =D

    PS。 2:我无法对此进行测试,因为我不在我的 PC ATM 上。

    【讨论】:

      猜你喜欢
      • 2022-06-22
      • 2020-12-10
      • 2019-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多