JSON(JavaScript Object Notation)作为轻量级的数据交换格式,几乎贯穿了所有Web项目:前端通过Ajax请求获取接口数据、第三方平台回调推送消息、配置文件以JSON格式存储等,这些场景都需要后端用PHP对JSON字符串进行解析。PHP从5.2版本开始就内置了完善的JSON处理函数,核心就是json_decode。虽然这个函数看起来简单,但实际使用中很多人会遇到解析结果变成对象取值不方便、解析失败返回null却不知道原因、中文变成乱码等问题。本文将系统讲解PHP解析JSON数据的完整知识体系。

一、json_decode函数的基本用法
json_decode是PHP解析JSON的核心函数,它的完整签名是json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)。第一个参数是要解析的JSON字符串,这是必填项。第二个参数$assoc非常关键:默认为false时,JSON对象会被解析成PHP的stdClass对象;如果设置为true,则会解析成关联数组,这是大多数开发者更习惯的方式。
<?php
$json = '{"name":"张三","age":25,"city":"北京"}';
// 默认解析为 stdClass 对象
$obj = json_decode($json);
echo $obj->name; // 输出:张三
// 第二个参数传 true,解析为关联数组
$arr = json_decode($json, true);
echo $arr['name']; // 输出:张三
echo $arr['age']; // 输出:25
?>第三个参数$depth定义最大嵌套深度,默认512层,超过这个深度的JSON会解析失败。第四个参数$options是位掩码,常用的选项包括JSON_BIGINT_AS_STRING,它可以把超大整数解析成字符串而不是float类型,避免精度丢失。例如解析包含很长用户ID的JSON时,不设置这个选项,ID可能会被转成科学计数法表示的浮点数。
<?php
$json = '{"user_id": 12345678901234567890}';
// 默认情况:大整数变成浮点数,精度丢失
$data = json_decode($json, true);
var_dump($data['user_id']); // float(1.2345678901235E+19)
// 使用 JSON_BIGINT_AS_STRING 选项保留原始值
$data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
var_dump($data['user_id']); // string(20) "12345678901234567890"
?>二、解析多维嵌套JSON与实际接口数据处理
实际项目中的JSON数据往往嵌套多层,比如一个订单接口返回的JSON中包含商品列表、收货地址、用户信息等。解析这类数据只需要记住一个原则:JSON对象对应PHP数组(当$assoc为true时),JSON数组对应PHP的索引数组。逐层使用中括号或箭头符号访问即可。
<?php
$json = '{
"order_id": "202312150001",
"buyer": {
"name": "李四",
"vip": true
},
"items": [
{"sku": "A1001", "price": 99.5, "num": 2},
{"sku": "A1002", "price": 45.0, "num": 1}
]
}';
$order = json_decode($json, true);
// 取嵌套对象的值
echo $order['buyer']['name']; // 李四
// 遍历JSON数组
$total = 0;
foreach ($order['items'] as $item) {
$total += $item['price'] * $item['num'];
}
echo "订单总金额:" . $total; // 订单总金额:244
?>在处理外部接口返回的JSON时,建议先对原始字符串做校验。有些接口返回的内容前面带有BOM头或者多余的空格换行,会导致json_decode直接失败。可以在解析前用trim去掉首尾空白,必要时去掉BOM头。另外,如果接口返回的HTTP状态码不是200,或者返回的是JSONP格式(带回调函数包裹),都需要先处理再解析。
三、解析失败的原因排查与调试技巧
json_decode解析失败时返回null,但返回null并不一定代表出错,因为合法的JSON字符串"null"解析结果也是null。要准确判断是否解析失败,必须配合json_last_error和json_last_error_msg这两个函数使用。前者返回错误码,后者返回可读的错误信息。
<?php
$json = "{'name':'张三'}"; // 错误:JSON的键和字符串值必须用双引号
$data = json_decode($json, true);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
echo "解析失败:" . json_last_error_msg();
// 输出:解析失败:Syntax error
}
?>常见的解析失败原因有几种:一是JSON中的字符串和键名使用了单引号,标准JSON只允许双引号;二是最后一个元素后面带了逗号(尾逗号);三是整个字符串为空;四是字符串编码不是UTF-8,PHP的JSON函数只支持UTF-8编码,如果来源是GBK编码的数据,需要先用iconv或mb_convert_encoding转换编码再解析。排查时可以把错误码和错误信息打出来对照,比如JSON_ERROR_SYNTAX表示语法错误,JSON_ERROR_UTF8表示编码问题。
四、json_encode与json_decode的配合及常见坑
解析JSON和生成JSON往往成对出现。PHP数组转JSON用json_encode,最容易踩的坑是中文被转义成\u4e2d\u6587形式的Unicode码点。虽然这样依然是合法的JSON,但可读性差且传输体积变大。解决办法是传入JSON_UNESCAPED_UNICODE选项。
<?php
$arr = ["name" => "张三", "city" => "北京"];
// 默认转义中文
$json1 = json_encode($arr);
echo $json1; // {"name":"\u5f20\u4e09","city":"\u5317\u4eac"}
// 不转义中文,输出原样文字
$json2 = json_encode($arr, JSON_UNESCAPED_UNICODE);
echo $json2; // {"name":"张三","city":"北京"}
// roundtrip:编码后再解码,验证数据完整性
$back = json_decode($json2, true);
var_dump($back === $arr); // bool(true)
?>还有一个高频坑是空JSON字符串。如果变量本身就是空字符串或false,json_decode会返回null,业务代码如果直接对这个null做数组遍历就会报错或产生逻辑问题。健壮的写法是在解析后统一做类型校验,用is_array判断结果是否为数组再继续处理。对于高版本PHP(7.3+),还可以使用json_try_decode的思路,或者通过JSON_THROW_ON_ERROR选项让JSON错误直接抛出异常,配合try-catch结构化处理错误,代码会更加清晰可靠。
总结来说,PHP解析JSON的核心是掌握json_decode的参数含义,养成传true获取数组、用json_last_error校验结果、注意UTF-8编码这三个习惯,基本就能应对项目中绝大多数JSON处理场景。
json_decodeJSON解析PHP修改时间:2026-09-02 22:49:02