
本文详解 php 中因误用 json_decode() 返回值结构导致 json 数据被嵌套为二维数组,从而在文件中产生冗余 [...] 的问题,并提供健壮、可扩展的 json 数组追加写入方案。
问题核心在于原始代码中这一行:
$tempArray = array(json_decode($currentData, true));
它将 json_decode(..., true) 解析出的关联数组(或空数组) 强制包裹进一个新数组,形成「数组的数组」——即二维结构。例如,若原 JSON 是 [],解码后为 [](空数组),再执行 array([]) 就得到 [[]];后续每次追加都会让嵌套层级加深,最终生成类似 [[], [{"name":"A",...}], [[], [{"name":"A",...}]]] 的非法结构,JSON 解析器会将其识别为顶层数组,导致前端读取时需多层索引,且语义混乱。
✅ 正确做法是:始终将 JSON 文件内容解析为一维关联数组(或空数组),并以统一键名管理数据集合。推荐使用 person_info 作为主键,确保结构清晰、可维护:
function writeToJSONFile($name, $username, $password, $email) {
// 1. 安全读取:检查文件是否存在,避免 file_get_contents 报错
if (file_exists('suckers.json')) {
$content = file_get_contents('suckers.json');
// 2. 解析为关联数组;若文件为空或非法 JSON,设为空数组
$currentData = !empty($content) ? json_decode($content, true) : [];
} else {
$currentData = [];
}
// 3. 确保 person_info 键存在且为数组(兼容首次写入)
if (!isset($currentData['person_info']) || !is_array($currentData['person_info'])) {
$currentData['person_info'] = [];
}
// 4. 追加新记录到 person_info 数组末尾
$currentData['person_info'][] = [
'name' => $name,
'username' => $username,
'password' => $password, // ⚠️ 注意:生产环境切勿明文存储密码!
'email' => $email
];
// 5. 编码为格式化 JSON(可选:增加 JSON_PRETTY_PRINT 提升可读性)
$toWrite = json_encode($currentData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// 6. 原子写入,防止并发写入冲突(简单场景可用;高并发建议加锁)
file_put_contents('suckers.json', $toWrite);
}? 关键改进点说明:
立即学习“PHP免费学习笔记(深入)”;
- 结构一致性:始终以 'person_info' => [...] 作为根级键,避免数据“漂浮”在顶层,便于后续增删查改;
- 容错设计:主动检测文件存在性与内容有效性,防止 json_decode() 解析失败导致 null 或 false 被误当数组;
- 类型安全:显式初始化 person_info 为数组,杜绝 [] += ... 类型错误;
- 可读性增强:使用 JSON_PRETTY_PRINT 输出缩进 JSON(开发调试友好),JSON_UNESCAPED_UNICODE 避免中文被编码为 \uXXXX;
- 安全性提醒:示例中密码仍为明文,真实项目必须使用 password_hash() 加密存储,并通过 password_verify() 校验。
? 额外建议:
- 若需支持删除/更新特定用户,可在 person_info 中为每条记录添加唯一 id 字段(如 uniqid() 或自增整数);
- 对于较大数据量,应考虑切换至 SQLite 或 MySQL,而非 JSON 文件;
- 建议搭配 json_last_error() 进行解析/编码错误排查,提升调试效率。
遵循此模式,即可彻底规避「多出方括号」问题,构建出结构规范、易于维护的 PHP JSON 持久化逻辑。











