php读取修改json文件需三步:读取→解析→回写,关键避坑点为编码、空文件、权限及json格式错误;须用file_get_contents+json_decode安全读取,检查返回值与解析错误,修改后用json_encode配合json_unescaped_unicode等选项格式化输出,并通过临时文件原子写入确保数据安全。

PHP 读取并修改 JSON 文件,核心就三步:读文件 → json_decode 解析 → 修改数组 → json_encode 回写 → 保存。但实际踩坑最多的是编码、空文件、权限和 JSON 格式错误这四类问题。
用 file_get_contents + json_decode 安全读取 JSON 文件
别直接 include 或 require JSON 文件——它不是 PHP 代码。必须用文件读取函数配合解析:
-
file_get_contents读取原始字符串,注意检查返回值是否为false(文件不存在或无读取权限) -
json_decode($json, true)的第二个参数设为true,确保返回关联数组而非对象,后续修改更直观 - 解析失败时
json_last_error()会返回非零值,常见如JSON_ERROR_SYNTAX(格式错误)、JSON_ERROR_DEPTH(嵌套过深) - 空文件或只有空白字符会导致
json_decode返回NULL,需提前判断:if ($content === '' || trim($content) === '') { $data = []; }
修改数组后用 json_encode 生成合法 JSON 字符串
PHP 数组改完后不能直接写入,json_encode 的选项直接影响可读性和兼容性:
- 中文字符默认被转成
uXXXX,加JSON_UNESCAPED_UNICODE保持可读:json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) -
JSON_PRETTY_PRINT增加缩进,方便人工查看,但会增大文件体积;生产环境可省略 - 如果数组含资源、闭包或循环引用,
json_encode会静默失败并返回false,务必检查返回值 - 浮点数精度问题:PHP 默认可能截断小数位,如需保留,改用
number_format预处理再存字符串字段
用 file_put_contents 原子化写入,避免写坏原文件
不要先 unlink 再写新文件——中断会导致数据丢失。推荐「写临时文件 → 原子重命名」:
立即学习“PHP免费学习笔记(深入)”;
- 生成临时文件名:
$tempFile = $jsonFile . '.tmp_' . uniqid(); - 用
file_put_contents($tempFile, $jsonString)写入,检查返回字节数是否匹配预期长度 - 成功后用
rename($tempFile, $jsonFile)替换原文件(linux/macos 下是原子操作) - windows 下
rename跨卷会失败,此时应先unlink($jsonFile)再rename,但需确保前一步写入已成功 - 写入前确认目录可写:
is_writable(dirname($jsonFile))
遇到 json_encode 返回空或 false 怎么快速定位
这不是“没报错就等于成功”,json_encode 失败只返回 false,没有异常抛出:
- 先用
var_dump($data)看结构,重点排查:NULL值、Resource类型(如未关闭的fopen句柄)、NaN或INF - 逐层简化数据:从顶层键开始注释掉子数组,缩小问题范围
- 用
json_last_error_msg()获取最后错误描述(PHP ≥ 5.5),比查错误码更直接 - 时间戳建议统一存为整数(
time()),避免DateTime对象无法序列化
最常被忽略的是文件编码和 bom:确保 JSON 文件是 UTF-8 无 BOM 格式,否则 json_decode 可能因开头不可见字符直接失败——用编辑器另存为「UTF-8(无 BOM)」最稳妥。