PHP 解析 JSON 入参,别只盯着 json_decode()
接口拿不到参数,不一定是前端没传。JSON 请求和普通表单不是一套入口,读错入口、误判 null、忽略大整数,都会把业务排查带偏。
HTTP Body → php://input → json_decode() → 错误码或异常 → 业务参数校验
支付回调、webhook、前后端分离接口里,json 入参很常见。真正容易出事的地方,不是会不会调用 json_decode(),而是请求体从哪里读、解析失败怎么判断、订单号这种大整数怎么保住精度。
一、JSON 请求别从 $_POST 里拿参数

$_POST 主要处理表单编码的数据。对方传的是 application/json 时,很多项目里 $_POST 会是空的,这时要读 php://input 里的原始请求体。
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
• 接口入口先记录 Content-Type 和请求体长度,别一上来就说参数没传。
• php://input 读到的是原始字符串,解析前可以做长度和空字符串判断。
• 如果兼容表单和 JSON,两套入口要分开处理,不要混在一个判断里。
请求体为空和入口读错,是两种问题。
我一般会在接口网关层把原始请求摘要打出来,排查回调失败时能少猜很多。
二、json_decode() 返回 null,不一定代表空数据

json_decode() 有个坑:解析合法的 JSON null 会返回 null,解析失败时也可能返回 null。只判断结果是不是空,很容易把坏 JSON 当成正常空数据。
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
// 记录 json_last_error_msg()
}
• 解析后立刻看 json_last_error(),不要等业务逻辑跑完再补救。
• 日志里记录 json_last_error_msg(),比只记“解析失败”有用。
• 空字符串、合法 null、语法错误,要拆成三个分支处理。
null 不是错误结论,它只是一个返回值。
这类问题在回调接口里尤其烦,因为对方只看到你返回失败,你这边却可能以为参数为空。
三、接口层建议用 JSON_THROW_ON_ERROR

如果项目 PHP 版本支持,接口入口可以用 JSON_THROW_ON_ERROR。这样坏 JSON 会直接抛出 JsonException,不用每次手动检查错误码,入口层也更好统一返回 400。
try {
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
// 返回参数错误
}
• 异常里不要直接记录完整请求体,大字段和敏感字段要截断。
• 业务校验和 JSON 语法校验分开,错误信息会清楚很多。
• 老项目如果没法改异常模式,就固定封装一个解析函数。
入口层越统一,业务层越干净。
我更喜欢在 Controller 前面就把 JSON 解析好,传进业务代码的已经是数组或明确的错误。
四、大整数订单号用 JSON_BIGINT_AS_STRING 兜住

支付订单号、雪花 ID、长数字流水号,不要轻易当数字处理。JSON 里看着是数字,进入 PHP 后可能因为精度问题变形,验签、查单、比对都会出问题。
$data = json_decode(
$raw,
true,
512,
JSON_BIGINT_AS_STRING | JSON_THROW_ON_ERROR
);
• 订单号这类标识最好让对方按字符串传,你这边也按字符串存。
• 如果无法控制对方格式,解析时加上 JSON_BIGINT_AS_STRING。
• 参数校验时区分数字金额和字符串 ID,别都丢进同一个规则。
标识符不是拿来计算的,保真比省事更重要。
JSON 解析这件事看着小,真正线上排查时很容易绕远。入口、错误、异常、大整数都处理清楚,后面的业务代码才不会被脏数据拖着走。
别把 JSON 入参当成天然干净的数据,它只是原始请求的一层包装。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











