json_encode索引数组变对象非bug,因PHP判定“非纯数字索引”:键不连续、含字符串键、数字字符串键、array_merge后键错乱;确保输出数组需用array_values()重置键,避免字符串键,优先[]追加;强制对象用(object)强转或JSON_FORCE_OBJECT。

json_encode 转索引数组时,默认输出 JSON 数组([]),但某些情况下会“意外”变成 JSON 对象({})。这不是 bug,而是 PHP 对数组结构的严格判定逻辑所致。
哪些情况会让索引数组被当成关联数组处理
只要 PHP 认为这个数组“不是纯数字索引”,就会转成对象。常见触发点有:
- 键名不连续:比如 $arr = [0 => 'a', 2 => 'c'],跳过了 1,json_encode 就视为非索引结构
- 键名含字符串:哪怕只加一个字符串键,如 $arr[0] = 'a'; $arr['total'] = 3;,整个数组就变成关联数组
- 键名是数字字符串:例如 $arr['0'] = 'a'; $arr['1'] = 'b';,PHP 不自动转换为整型键,仍按字符串键处理
- 使用 array_merge 合并后键重排失败:比如合并两个索引数组但中间有空值,可能产生非顺序数字键
如何确保输出为标准 JSON 数组([])
核心思路是让数组满足“从 0 开始、连续、全为整型键”的条件:
- 用 array_values() 重置键名:即使原数组键乱,json_encode(array_values($arr)) 可强制归零连续
- 避免手动赋值带引号的数字键:写 $arr[0],别写 $arr['0']
- 构建数组时优先用 [] 语法追加:如 $arr[] = 'x';,而不是 $arr[$i] = 'x';(除非 $i 精确可控)
- 检查键类型:可用 array_keys($arr) + is_int() 验证是否全为整型键
想强制输出 JSON 对象({})怎么办
即使输入是索引数组,也有明确方式转成对象格式:
- 用类型强转:json_encode((object)$arr)
- 加选项常量:json_encode($arr, JSON_FORCE_OBJECT)
- 或先转为带字符串键的关联结构:$obj = []; foreach ($arr as $k => $v) $obj[(string)$k] = $v;,再编码
中文和格式化等实用控制项
输出可读性与兼容性也需兼顾:
- 保留中文原文:加 JSON_UNESCAPED_UNICODE,如 json_encode($arr, JSON_UNESCAPED_UNICODE)
- 美化缩进(调试用):叠加 JSON_PRETTY_PRINT
- 检测失败原因:若返回 false,调用 json_last_error_msg() 查具体错误
- 注意 PHP 版本:JSON_UNESCAPED_UNICODE 要求 PHP ≥ 5.4.0


















