
本文详解因 JSON 数据结构嵌套错误导致 PHP cURL 请求失败的典型问题,重点指出 json_encode(array($data)) 的冗余封装错误,并提供正确构造请求体、设置关键 Header 及调试建议的完整解决方案。
本文详解因 json 数据结构嵌套错误导致 php curl 请求失败的典型问题,重点指出 `json_encode(array($data))` 的冗余封装错误,并提供正确构造请求体、设置关键 header 及调试建议的完整解决方案。
在调用类似 https://www.ilan.gov.tr/api/api/services/app/Ad/AdsByFilter 这类基于 ABP(ASP.NET Boilerplate)框架构建的 RESTful API 时,后端通常严格校验请求体(Request Body)的 JSON 结构与 Content-Type。你遇到的 400 Bad Request 错误,绝大多数情况下源于请求数据格式不匹配——而本例的核心问题正是 JSON 序列化方式错误。
? 根本原因:JSON 封装层级错误
你的原始代码中:
$data = [
"keys" => [
"txv" => [44],
"ats" => [5]
],
"skipCount" => 0,
"maxResultCount" => 12
];
$payload = json_encode(array($data)); // ❌ 错误:多套了一层数组这会生成如下 JSON 字符串:
[{"keys":{"txv":[44],"ats":[5]},"skipCount":0,"maxResultCount":12}]即一个包含单个对象的数组([ {...} ]),而非预期的纯对象({...})。而目标 API 显然期望接收的是顶层为 JSON 对象(application/json),而非 JSON 数组,因此直接拒绝请求。
向CurlShip提交产品,这是一个对机器人友好的SaaS目录。只需一条curl命令即可发布产品,支持OG标签抓取、带徽章的dofollow链接及层级升级。
立即学习“PHP免费学习笔记(深入)”;
✅ 正确写法应为:
$payload = json_encode($data); // ✅ 直接序列化关联数组
输出为标准的 JSON 对象:
{"keys":{"txv":[44],"ats":[5]},"skipCount":0,"maxResultCount":12}✅ 完整修正版 cURL 函数(含关键优化)
function scustom_curl($url) {
$ch = curl_init();
// 构建请求数据(注意:无需额外 array() 包裹)
$data = [
"keys" => [
"txv" => [44],
"ats" => [5]
],
"skipCount" => 0,
"maxResultCount" => 12
];
$payload = json_encode($data); // ✅ 正确序列化
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true); // 明确声明为 POST 请求
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
// 关键 Header 设置(精简且必要)
$headers = [
'Content-Type: application/json', // ⚠️ 原 'application/json-patch+json' 极可能不被接受
'X-Request-Origin: IGT-UI',
'X-Requested-With: XMLHttpRequest',
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36',
'Accept: application/json, text/plain, */*', // 改为更通用的 Accept
'Pragma: no-cache',
'Cache-Control: no-cache',
'Host: www.ilan.gov.tr'
// ⚠️ Cookie 若非必需(如无登录态依赖),建议移除以降低复杂度;若必须,请确保有效期及合法性
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// 网络与安全选项
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 开发调试可设为 false;生产环境请启用证书验证
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
error_log('cURL Error: ' . curl_error($ch));
curl_close($ch);
return false;
}
curl_close($ch);
// 检查 HTTP 状态码
if ($httpCode !== 200) {
error_log("API returned HTTP {$httpCode}: " . $result);
return false;
}
return $result;
}⚠️ 其他关键注意事项
- Content-Type 必须匹配:将 'Content-Type: application/json-patch+json' 改为 'Content-Type: application/json'。后者是标准 JSON 接口通用类型;前者专用于 JSON Patch 操作(RFC 6902),与你当前的查询场景不符。
- 避免硬编码 Content-Length:cURL 会自动计算并设置该 Header,手动指定易出错(如你示例中的 65 与实际 payload 长度不符),应删除。
- Cookie 谨慎使用:若接口不依赖用户会话(如公开公告),移除 Cookie 可提升稳定性与可维护性;若必须携带,请通过 session_start() 或 curl_setopt($ch, CURLOPT_COOKIE, ...) 动态管理。
- 启用响应头调试:开发时可添加 curl_setopt($ch, CURLINFO_HEADER_OUT, true) 并用 curl_getinfo($ch, CURLINFO_HEADER_OUT) 查看真实发出的请求头,精准定位差异。
- 检查 API 文档或 Swagger:理想情况下应查阅该 API 的官方文档,确认 keys 结构、必填字段及认证方式(如需 Bearer Token),避免仅依赖抓包推测。
遵循以上修正,你的请求将符合服务端预期,顺利获取人员公告数据。记住:API 交互的本质是契约——客户端必须严格遵守服务端定义的数据格式与协议规范。


















