如何使用动态键遍历 PHP 对象 [duplicate]

How to loop through PHP object with dynamic keys [duplicate]

提问人:John Doe 提问时间:12/3/2010 最后编辑:Cedric IpkissJohn Doe 更新时间:12/28/2022 访问量:995391

问:

这个问题在这里已经有答案了:
去年关闭。

这篇文章在 11 个月前被编辑并提交审核,但未能重新打开帖子:

原始关闭原因未解决

我尝试使用PHP解析JSON文件。但我现在被困住了。

这是我的JSON文件的内容:

{
    "John": {
        "status":"Wait"
    },
    "Jennifer": {
        "status":"Active"
    },
    "James": {
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
    }
}

这就是我到目前为止尝试过的:

<?php

$string = file_get_contents("/home/michael/test.json");
$json_a = json_decode($string, true);

echo $json_a['John'][status];
echo $json_a['Jennifer'][status];

但是因为我事先不知道名称(如 、)以及所有可用的键和值(如 )、,所以我认为我需要创建一些 foreach 循环。'John''Jennifer''age''count'

我希望能举个例子。

PHP 的JSON

评论

65赞 Stefan Mai 12/3/2010
你走在正确的轨道上。查找 foreach 的语法(应获取键和值)。不要放弃!
11赞 Bojangles 12/3/2010
@Stefan Mai:应该是你想要的:-)foreach($variable as $key => $val)
0赞 Álvaro González 12/3/2010
旁注:我建议你配置你的PHP设置以显示所有类型的错误消息,包括notices
0赞 salathe 12/3/2010
您能否详细说明一下您试图通过“解析”JSON 获得什么:即您试图用代码完成什么任务(例如:“输出所有状态”、“查找状态为 xyz 的名称”、“查找 xyz 的所有信息”)?
0赞 mario 2/4/2018
X-Ref:如何使用PHP从JSON中提取数据?(对于更挑剔的数组遍历)。

答:

42赞 Thariama 12/3/2010 #1

尝试

<?php
$string = file_get_contents("/home/michael/test.json");
$json_a = json_decode($string,true);

foreach ($json_a as $key => $value){
  echo  $key . ':' . $value;
}
?>

评论

6赞 mickmackusa 9/1/2018
尝试这个答案在 StackOverflow 上的价值很低,因为它们对教育 OP 和未来的研究人员几乎没有帮助。如果您打算在页面上留下此答案,请解释您的答案如何工作以及为什么建议这样做。
0赞 mickmackusa 3/28/2019
正如 BoltClock 的回答所证明的那样,对于问题的样本数据,这个答案是不正确的。
0赞 Muhammad Omer Aslam 9/9/2019
它如何迭代嵌套的多点数组
8赞 Alex 12/3/2010 #2

使用循环作为键值对循环遍历 JSON。进行类型检查以确定是否需要执行更多循环。foreach

foreach($json_a as $key => $value) {
    echo $key;
    if (gettype($value) == "object") {
        foreach ($value as $key => $value) {
          # and so on
        }
    }
}

评论

0赞 Ignacio Vazquez-Abrams 12/3/2010
或者更好的是,事先知道结构是什么。
165赞 BoltClock 12/3/2010 #3

我不敢相信有这么多人在没有正确阅读 JSON 的情况下发布答案。

如果单独进行 foreach 迭代,则具有对象的对象。即使作为第二个参数传入,也有一个二维数组。如果你循环遍历第一维度,你就不能像那样回响第二个维度。所以这是错误的:$json_atrue

foreach ($json_a as $k => $v) {
   echo $k, ' : ', $v;
}

要呼应每个人的状态,请尝试以下操作:

<?php

$string = file_get_contents("/home/michael/test.json");
if ($string === false) {
    // deal with error...
}

$json_a = json_decode($string, true);
if ($json_a === null) {
    // deal with error...
}

foreach ($json_a as $person_name => $person_a) {
    echo $person_a['status'];
}

?>

评论

7赞 eQ19 4/16/2015
如果 php 和 json 文件在同一个目录下,我们可以用 json 读取(无需放路径)。file_get_contents("test.json");
2赞 Flimm 8/28/2019
@Chetabahana 这实际上是不正确的。如果使用类似 的相对路径,则该路径是相对于当前目录计算的,而不一定是 PHP 脚本所在的位置。在 bash 上,可以通过键入 来发现当前目录。test.jsonpwd
0赞 Nguai al 1/21/2021
@Flimm 如果PHP和JSON并在同一目录下执行,则无需指定JSON文件的绝对路径。正确?
1赞 Flimm 1/22/2021
@Nguaial 这取决于当前的工作目录是什么。例如,假设您有一个 PHP 文件和一个 JSON 文件。如果您当前的工作是 ,那么要运行 PHP 文件,您需要键入 .在这种情况下,PHP 文件需要引用 JSON 文件,因为相对路径是相对于当前工作目录的,而不一定是 PHP 文件的父目录。/home/user/project/test.php/home/user/project/json.json/home/userphp project/test.phpproject/test.json
355赞 Gordon 12/3/2010 #4

若要循环访问多维数组,可以使用 RecursiveArrayIterator

$jsonIterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator(json_decode($json, TRUE)),
    RecursiveIteratorIterator::SELF_FIRST);

foreach ($jsonIterator as $key => $val) {
    if(is_array($val)) {
        echo "$key:\n";
    } else {
        echo "$key => $val\n";
    }
}

输出:

John:
status => Wait
Jennifer:
status => Active
James:
status => Active
age => 56
count => 10
progress => 0.0029857
bad => 0

在CodePad上运行

评论

13赞 Álvaro González 12/3/2010
与旧的foreach相比,这种方法是否具有任何特殊优势?
20赞 Gordon 12/3/2010
@Álvaro显然。使用 foreach,您只能递归一个深度级别。使用上述方法,您可以在多级数组上递归。另外,整个东西都封装在 OOP 中,所以你有更好的重用,你可以轻松地在 UnitTests 中模拟它,而且你可以将迭代器与其他迭代器堆叠在一起,做不同的事情,比如限制、缓存、过滤等等。除了您可能想要创建的任何自定义迭代器之外。
0赞 Álvaro González 12/3/2010
好吧,我没有考虑到嵌套级别是可变的。在这种情况下,这比递归函数更简洁。
0赞 Jesse Chisholm 8/30/2015
但是,这种样式解析会留下一些歧义。例如,与 没有区别。那是结构性的孩子丢失了。{'John':{'status':'waiting', 'Mary':{'status','nested'}}, 'Suzy':{'status:'waiting'} }{'John':{'status':'waiting'}, 'Mary':{'status','nested'}, 'Suzy':{'status:'waiting'} }MaryJohn
0赞 Gordon 8/30/2015
@Jesse php.net/manual/en/class.recursiveiteratoriterator.php 可以让您检测深度。
-1赞 muneeb 1/27/2012 #5

你必须像这样给予:

echo  $json_a['John']['status']; 

echo "<>"

echo  $json_a['Jennifer']['status'];

br inside <>

这给出了结果:

wait
active

评论

1赞 mickmackusa 9/1/2018
Do Like This 答案在 StackOverflow 上价值不大,因为它们对教育 OP 和未来的研究人员几乎没有帮助。如果您打算在页面上留下此答案,请解释您的答案如何工作以及为什么建议这样做。
0赞 mickmackusa 3/28/2019
这个答案似乎误解了这个问题。OP 事先不知道“名称”键,因此无法对其进行硬编码。这个答案是不正确的。
3赞 Hamender 5/31/2013 #6

尝试一下:

foreach ($json_a as $key => $value)
 {
   echo $key, ' : ';
   foreach($value as $v)
   {
       echo $v."  ";
   }
}

评论

2赞 mickmackusa 9/1/2018
尝试这个答案在 StackOverflow 上的价值很低,因为它们对教育 OP 和未来的研究人员几乎没有帮助。如果您打算在页面上留下此答案,请解释您的答案如何工作以及为什么建议这样做。
9赞 Indrajeet Singh 6/11/2014 #7

尝试:

$string = file_get_contents("/home/michael/test.json");
$json = json_decode($string, true);

foreach ($json as $key => $value) {
    if (!is_array($value)) {
        echo $key . '=>' . $value . '<br />';
    } else {
        foreach ($value as $key => $val) {
            echo $key . '=>' . $val . '<br />';
        }
    }
}

评论

2赞 mickmackusa 9/1/2018
尝试这个答案在 StackOverflow 上的价值很低,因为它们对教育 OP 和未来的研究人员几乎没有帮助。如果您打算在页面上留下此答案,请解释您的答案如何工作以及为什么建议这样做。
1赞 Daniel Blanco 8/25/2014 #8

当你解码一个json字符串时,你会得到一个对象。不是数组。因此,查看所得到的结构的最好方法是对解码进行var_dump。(这个var_dump可以帮助你理解结构,主要是在复杂的情况下)。

<?php
     $json = file_get_contents('/home/michael/test.json');
     $json_a = json_decode($json);
     var_dump($json_a); // just to see the structure. It will help you for future cases
     echo "\n";
     foreach($json_a as $row){
         echo $row->status;
         echo "\n";
     }
?>
1赞 Sreejith Nhaloor 11/19/2014 #9
$json_a = json_decode($string, TRUE);
$json_o = json_decode($string);



foreach($json_a as $person => $value)
{
    foreach($value as $key => $personal)
    {
        echo $person. " with ".$key . " is ".$personal;
        echo "<br>";
    }

}

评论

6赞 Taryn East 11/19/2014
嗨,这很可能能解决问题......但是,如果您可以编辑您的答案并提供有关其工作原理和原因的更多解释,那就太好了:)别忘了 - Stack overflow 上有很多新手,他们可以从你的专业知识中学到一两件事 - 对你来说显而易见的东西对他们来说可能不是这样。
62赞 swift 12/17/2014 #10

最优雅的解决方案:

$shipments = json_decode(file_get_contents("shipments.js"), true);
print_r($shipments);

请记住,json 文件必须以 UTF-8 编码,而无需 BOM。如果文件具有 BOM,则json_decode将返回 NULL。

或者:

$shipments = json_encode(json_decode(file_get_contents("shipments.js"), true));
echo $shipments;

评论

7赞 zipzit 2/12/2015
真是太棒了,但整个物料清单 (BOM) 的事情让我完全困惑。的。。。你在谈论什么?我是唯一一个对使用神秘的无法解释的缩写感到恼火的人吗?可以使用缩写,但请解释首次使用时(WFU)...谢谢。
9赞 swift 3/2/2015
BOM = 字节顺序标记。
3赞 swift 3/2/2015
en.wikipedia.org/wiki/Byte_order_mark如果您在 mac 和 pc 上使用 json,则会遇到典型的问题,因为它们使用不同的默认文本格式。
0赞 mickmackusa 3/28/2019
这篇文章并不试图回答发布的问题
20赞 David 2/21/2015 #11

没有人指出你的开头“标签”是错误的,这完全超出了我的范围。您正在使用 {} 创建一个对象,而您可以使用 [] 创建一个数组。

[ // <-- Note that I changed this
    {
        "name" : "john", // And moved the name here.
        "status":"Wait"
    },
    {
        "name" : "Jennifer",
        "status":"Active"
    },
    {
        "name" : "James",
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
    }
] // <-- And this.

通过此更改,json 将被解析为数组而不是对象。有了这个数组,你可以做任何你想做的事,比如循环等。

评论

0赞 Stephen Adelakun 8/23/2016
你指出数组的东西是对的。
0赞 Stephen Adelakun 8/23/2016
哦,我的。我应该补充一点,在转换为数组时,您似乎已经删除了 OP 的 json 中的键。所以OP是对的。
0赞 David 8/25/2016
“但因为我不知道名字(比如约翰、詹妮弗)和所有可用的钥匙”。他似乎不知道钥匙,所以遍历收藏品的唯一方法是循环。这告诉我他不会通过键直接访问这些值。
0赞 mickmackusa 3/28/2019
这篇文章未能回答如何解析 json 字符串并从未知的第一级键访问子数组元素的问题。这不是答案,应该是问题下的评论。看起来您建议应该读取文件,然后通过字符串函数进行更改以适合您的偏好。我不明白。
0赞 David 4/2/2019
不,我指出文件的结构对于他正在阅读它的目的是错误的。因此,它确实回答了这个问题。而且你似乎确实不明白,因为我没有说字符串函数。这太傻了。
0赞 The Bumpaster 7/29/2016 #12

回显所有 json 值的最快方法是使用循环中的循环,第一个循环将获取所有对象,第二个循环将获取值......

foreach($data as $object) {

        foreach($object as $value) {

            echo $value;

        }

    }
9赞 Diptesh Atha 8/3/2016 #13

更多标准答案:

$jsondata = file_get_contents(PATH_TO_JSON_FILE."/jsonfile.json");

$array = json_decode($jsondata,true);

foreach($array as $k=>$val):
    echo '<b>Name: '.$k.'</b></br>';
    $keys = array_keys($val);
    foreach($keys as $key):
        echo '&nbsp;'.ucfirst($key).' = '.$val[$key].'</br>';
    endforeach;
endforeach;

输出为:

Name: John
 Status = Wait
Name: Jennifer
 Status = Active
Name: James
 Status = Active
 Age = 56
 Count = 10
 Progress = 0.0029857
 Bad = 0

评论

0赞 Danish 8/25/2018
或者可以说是第一行$data = json_decode(file_get_contents("db.json"), true);
3赞 mickmackusa 9/1/2018
纯代码答案在 StackOverflow 上价值不大,因为它们对教育 OP 和未来的研究人员几乎没有什么作用。如果您打算在页面上留下此答案,请解释您的答案如何工作以及为什么建议这样做。
1赞 mickmackusa 3/28/2019
当以下循环可以自行提供所有数据时,在此处调用是没有意义的。我不认为我同意“更标准”,我能想到一些更好的变量名称。array_keys()foreach()$val
16赞 vivek 10/6/2016 #14

试试这个

    $json_data = '{
    "John": {
        "status":"Wait"
    },
    "Jennifer": {
        "status":"Active"
    },
    "James": {
        "status":"Active",
        "age":56,
        "count":10,
        "progress":0.0029857,
        "bad":0
      }
     }';

    $decode_data = json_decode($json_data);
    foreach($decode_data as $key=>$value){

            print_r($value);
    }

评论

11赞 mickmackusa 9/1/2018
尝试这个答案在 StackOverflow 上的价值很低,因为它们对教育 OP 和未来的研究人员几乎没有帮助。如果您打算在页面上留下此答案,请解释您的答案如何工作以及为什么建议这样做。
0赞 ibnɘꟻ 4/5/2021
OP 要求从 JSON 文件解析数据,而不是从代码中的变量解析 JSON。
8赞 sunny bhadania 4/3/2018 #15
<?php
$json = '{
    "response": {
        "data": [{"identifier": "Be Soft Drinker, Inc.", "entityName": "BusinessPartner"}],
        "status": 0,
        "totalRows": 83,
        "startRow": 0,
        "endRow": 82
    }
}';
$json = json_decode($json, true);
//echo '<pre>'; print_r($json); exit;
echo $json['response']['data'][0]['identifier'];
$json['response']['data'][0]['entityName']
echo $json['response']['status']; 
echo $json['response']['totalRows']; 
echo $json['response']['startRow']; 
echo $json['response']['endRow']; 

?>

评论

4赞 mickmackusa 9/1/2018
纯代码答案在 StackOverflow 上价值不大,因为它们对教育 OP 和未来的研究人员几乎没有什么作用。如果您打算在页面上留下此答案,请解释您的答案如何工作以及为什么建议这样做。
1赞 mickmackusa 3/28/2019
请不要忽略 OP 提供的样本数据,而是尝试以与发布的问题直接相关的方式回答问题。
-1赞 HarisH Sharma 3/12/2019 #16

我正在使用以下代码将json转换为数组, 如果 JSON 有效,则运行良好,并将返回一个数组, 但是如果JSON格式不正确,它将返回,PHPjson_decode()NULL

<?php
function jsonDecode1($json){
    $arr = json_decode($json, true);
    return $arr;
}

// In case of malformed JSON, it will return NULL
var_dump( jsonDecode1($json) );
?>

如果在格式错误的 JSON 的情况下,您只需要数组,那么您可以使用此函数,

<?php
function jsonDecode2($json){
    $arr = (array) json_decode($json, true);
    return $arr;
}

// In case of malformed JSON, it will return an empty array()
var_dump( jsonDecode2($json) );
?>

如果在格式错误的 JSON 的情况下,您想停止代码执行,那么您可以使用此函数,

<?php
function jsonDecode3($json){
    $arr = (array) json_decode($json, true);

    if(empty(json_last_error())){
        return $arr;
    }
    else{
        throw new ErrorException( json_last_error_msg() );
    }
}

// In case of malformed JSON, Fatal error will be generated
var_dump( jsonDecode3($json) );
?>

评论

0赞 mickmackusa 3/28/2019
empty()是不必要的开销。只需使用 .此外,这未能回答OP提出的问题。它不是“如何将值转换为数组”,也不是“如何检查JSON错误”。我将这篇文章标记为“不是答案”。!json_last_error()
0赞 HarisH Sharma 3/29/2019
但是没有人解决 json 格式不正确的情况,所以只有 json_decode() 是不够的,也应该检查有效的 json,它是你的思想人,如果你愿意,请标记,我不是来赚取积分的,作为开发人员,仅提供解决方案是不够的,优点和缺点也一样,
0赞 mickmackusa 3/29/2019
每个答案都应该回答所提出的确切问题。如果每个答案都涉及相关的主题,那么研究人员将更难找到他们真正在寻找的解决方案。有时我会用错误检查来打包我的答案(通常与我的 mysql 答案一起),因为它是正确解决方案的合理伴奏。例如,我绝不会纯粹地在“如何交叉连接”问题上发布错误说明,因为这不会回答发布的问题。你现在明白为什么你的帖子不合适了吗?它忽视了这个问题。
0赞 mickmackusa 3/29/2019
您发布了错误问题的正确答案。更好的地方可能包括:stackoverflow.com/q/2348152/2943403stackoverflow.com/q/6041741/2943403stackoverflow.com/q/5970270/2943403 等等。