PHPJSON怎么传参_php通过api发送json数据的操作【详解】

7次阅读

phpcurljson必须设content-type: application/json和accept: application/json,手动json_encode后传字符串给curlopt_postfields,并校验编码结果、检查http状态码。

PHPJSON怎么传参_php通过api发送json数据的操作【详解】

PHP用cURL发JSON数据,Content-Type必须设对

不设或设错 Content-Type,后端大概率收不到 $_POST 或解析为空。PHP默认把JSON当表单提交,服务端按 application/x-www-form-urlencoded 解析,自然失败。

正确做法是显式设置为 application/json

curl_setopt($ch, CURLOPT_HTTPHEADER, [     'Content-Type: application/json',     'Accept: application/json' ]);
  • 只设 Content-Type 不够,加 Accept 能避免某些网关(如nginx、Cloudflare)拦截“非标准”请求头
  • 别用 application/json; charset=utf-8 —— 多数API不认分号后的参数,反而触发415错误
  • 如果后端是thinkphp/laravel等框架,没设对这个头,request()->json()file_get_contents('php://input') 可能读不到原始JSON

json_encode()前必须检查数据结构和编码

json_encode() 返回 false 却没判空,发出去的就是空字符串或乱码,接口直接报400。常见原因不是语法错,而是中文、资源句柄、循环引用这些隐性问题。

实操建议:

立即学习PHP免费学习笔记(深入)”;

  • 传参前先跑一遍:$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
  • 立刻检查:if ($json === false) { throw new Exception('JSON encode failed: ' . json_last_Error_msg()); }
  • 特别注意:数组里混了 Resource(比如未关闭的文件句柄)、NaNINFjson_encode() 会静默失败
  • 数据库查出的字段含mysqlTINYint(1),PHP可能转成布尔,而有些API拒绝布尔值——提前用 (int) 强转更稳妥

POST body不能靠CURLOPT_POSTFIELDS自动序列化

直接传数组给 CURLOPT_POSTFIELDS,cURL会把它当 application/x-www-form-urlencoded 发,即使你设了JSON头也没用。这是最常踩的坑。

必须手动转成字符串再传:

$data = ['name' => '张三', 'score' => 95]; $json = json_encode($data); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); // 注意:这里是字符串,不是数组
  • 别写 curl_setopt($ch, CURLOPT_POSTFIELDS, $data) —— 看似省事,实际发的是键值对,不是JSON
  • 如果用了 http_build_query() 包一层,结果是 name=%E5%BC%A0%E4%B8%89&score=95,后端收到的是URL编码字符串,不是JSON对象
  • 大JSON体(>1MB)要考虑内存:用 fopen('php://temp', 'r+') 写入再传流,避免一次性加载进内存

调试时别只看curl_exec()返回值

curl_exec() 返回空字符串,不等于请求失败;返回一串JSON,也不代表业务成功。很多API在HTTP 200下仍返回错误体(比如 {"code":401,"msg":"Token expired"})。

  • 务必配合 curl_getinfo($ch, CURLINFO_HTTP_CODE) 检查真实状态码
  • 开启错误输出:curl_setopt($ch, CURLOPT_FAILONERROR, true),让4xx/5xx直接抛异常
  • 抓包验证最准:用 curl_setopt($ch, CURLOPT_VERBOSE, true) + fopen('php://stderr'),看实际发出的请求头和body长啥样
  • 线上环境禁用 verbose,但至少保留 CURLINFO_HEADER_OUT 记录请求头,方便出问题时回溯

真正难的不是拼出JSON,是确保它从PHP内存出发,穿过cURL、TCP、代理、防火墙,最后被对方API按预期解析——每个环节都可能悄悄改掉你的数据。别信“应该没问题”,每个header、每个encode、每个error check,都得亲手验过。

text=ZqhQzanResources