php安全接收json需读取php://input流并校验content-type为application/json,用json_decode解析后配合json_last_error检查错误,注意编码转换与空值处理,对接第三方时应使用空合并操作符和类型断言。

PHP怎么安全接收外部发来的JSON数据
直接用 $_POST 或 $_GET 拿不到——因为 JSON 通常走 raw body,不是表单编码。必须手动读取输入流,再解析。
- 用
file_get_contents('php://input')读原始请求体,这是最可靠方式;$_POST在 Content-Type 是application/json时为空 - 务必检查
Content-Type请求头是否为application/json,避免误处理其他格式数据 - 解析前先判断内容是否为空或非法:用
json_decode($raw, true),再检查返回值是否为null,并用json_last_error()定位错误类型(比如JSON_ERROR_SYNTAX) - 别跳过字符编码校验:如果 JSON 含非 UTF-8 字符(如 GBK),
json_decode()会静默失败,建议提前用mb_detect_encoding()+mb_convert_encoding()处理
为什么 json_decode() 返回 null 却没报错
这不是 bug,是 PHP 的默认行为:只要 JSON 格式不合法、或含不可见控制字符(如 \u0000)、或编码不对,json_decode() 就返回 null,且不抛异常。
- 必须配合
json_last_error()和json_last_error_msg()查原因,例如json_last_error() === JSON_ERROR_UTF8表示编码问题 - 常见隐形坑:前端用
JSON.stringify({ a: undefined }),结果生成{"a":null}看似合法,但若字段被后端强校验“必须存在”,逻辑就断了 - 调试时可用
bin2hex($raw)看原始字节,确认有没有 BOM 或不可见字符
对接第三方 API 时如何防止 JSON 注入或结构错乱
第三方给的 JSON 结构可能随时变,字段缺失、类型突变、嵌套加深都会让 isset($data['user']['name']) 这类写法崩掉。
- 别直接链式访问深层字段,改用空合并操作符:
$name = $data['user']['name'] ?? '未知'(PHP 7.0+) - 对关键字段做类型断言:比如用
is_string($data['id']) && ctype_digit($data['id'])替代单纯!empty() - 用
filter_var()配合FILTER_VALIDATE_EMAIL或FILTER_SANITIZE_NUMBER_INT做二次清洗,别只信json_decode的结果 - 如果第三方文档写“字段可选”,代码里就得预设默认值或明确处理分支,不能靠“一般都有”来赌
用 cURL 发送 JSON 到第三方 API 的关键配置点
发错 header 或 body 编码,对方收不到有效 JSON,还常返回 400 却不说明白原因。
立即学习“PHP免费学习笔记(深入)”;
- 必须显式设置两个 header:
Content-Type: application/json和Accept: application/json - body 必须是字符串,不是数组:用
json_encode($payload, JSON_UNESCAPED_UNICODE),否则中文变 \uXXXX - cURL 要关掉
CURLOPT_RETURNTRANSFER默认是 true,但别漏设CURLOPT_POSTFIELDS为字符串,设成数组会自动转成 multipart/form-data - 加个
CURLOPT_HTTPHEADER数组,别用字符串拼接,避免 header 冒号后多空格导致某些网关拒绝
text/plain 却硬当成 JSON 解析。











