
本文详解如何正确遍历含数字键的 json 对象结构,解决因误将数组当作对象访问导致的 “trying to get Property of non-Object” 错误,并提供健壮的解码与遍历方案。
在 php 中解析 jsON 数据时,结构理解偏差是引发运行时 Notice 的常见原因。你遇到的错误 Notice: Trying to get property ‘mapname’ of non-object 并非源于 json 解析失败,而是因为对解码后数据类型的误判:json_decode() 默认返回 stdClass 对象,但你的 JSON 根结构是一个关联数组(对象),其键为字符串 “1”,而该键对应的值是一个索引数组(包含一个对象),而非单个对象。
原始 JSON 结构如下:
{ "1": [ { "servname": "Test place", "mapname": "Crossroads", "ip": "1.1.1.1", "port": "1337", "plimit": "12" } ] }
经 json_decode($json) 后,$decoded 是一个 stdClass 实例,拥有属性 ->{“1”},其值为一个 PHP 索引数组(array[0] 是目标对象)。因此,直接 foreach ($decoded as $game) 会将 $game 赋值为该数组(即 [ {…} ]),而非内部对象 —— 此时 $game->mapname 就是在尝试访问数组的属性,自然报错。
✅ 正确做法有两种:
立即学习“PHP免费学习笔记(深入)”;
方案一:两层循环(推荐,语义清晰、可扩展性强)
$gameArray) { // 内层遍历该键对应的游戏列表(可能含多个服务器) foreach ($gameArray as $game) { echo $game->mapname . "n"; // 输出: Crossroads } } ?>
方案二:直接访问首个元素(仅适用于确定每组仅一个对象)
mapname . "n"; } } ?>
⚠️ 重要注意事项:
- 避免使用纯数字键名:虽然 JSON 允许 “1” 作为键,但 PHP 中无法通过 $obj->1 访问(语法错误),只能用 $obj->{‘1’} 或更安全的 (Array)$obj[‘1’]。建议在数据设计阶段改用语义化键名(如 “server_group_1″),提升可维护性与兼容性。
- 始终验证解码结果:json_decode() 在失败时返回 NULL,需用 json_last_error() 检查;同时确认 foreach 遍历的是非空、预期类型的数据。
- 类型安全增强:若需强类型保障,可启用 json_decode($json, true) 返回关联数组,再用 $gameArray[0][‘mapname’] 访问(注意此时是数组语法,非对象语法)。
总结:该错误本质是「混淆了对象属性与数组元素」。掌握 JSON → PHP 数据类型的映射规则(对象 ↔ stdClass / 关联数组,数组 ↔ 索引数组),并辅以类型检查与分层遍历,即可稳健处理任意嵌套结构。