
本文详解如何正确遍历含数字键的 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 / 关联数组,数组 ↔ 索引数组),并辅以类型检查与分层遍历,即可稳健处理任意嵌套结构。











