API 返回 400 Bad Request 排查指南:JSON 请求格式、Content-Type、参数位置与常见报错
在调试接口时400 Bad Request是新手最容易遇到的错误之一。很多人的第一反应是是不是某个参数值写错了这个判断有可能成立但并不完整。400 Bad Request的核心含义是服务器认为这次 HTTP 请求不符合要求无法继续理解或处理。它可能是业务参数错误也可能是更底层的问题比如JSON 语法不合法Content-Type和 Body 不匹配Body 为空参数放错了位置字段类型与接口文档不一致URL 中特殊字符没有编码请求还没进入业务接口就被网关、代理或协议层拦截。所以排查 400 时不建议一开始就盯着某个字段值。更稳定的排查顺序应该是Method / URL 是否正确 ↓ Headers 是否正确 ↓ Body 是否真的发出去了 ↓ JSON 语法是否合法 ↓ 字段名、字段类型、必填项是否符合文档 ↓ 是否被网关、代理或协议层提前拦截下面按实际调接口的流程整理一套适合排查 JSON API 400 的方法。1. 先看响应体400 不等于“参数值一定错”接口返回 400 时第一步不是改参数而是先看响应体里有没有更具体的错误信息。常见提示包括Invalid JSON Unexpected token Missing required field Required request body is missing Content-Type not supported type mismatch Cannot deserialize value这些信息比单独一个400 Bad Request有用得多。例如{ error: Invalid JSON }这种情况通常说明问题在 JSON 语法或请求体格式上服务端甚至还没开始处理业务字段。再例如{ error: Missing required field: userId }这更像是接口参数问题说明必填字段userId没有传。因此可以先做一个判断如果提示Invalid JSON、Unexpected token优先查 JSON 语法和 Body如果提示Missing required field、type mismatch优先查字段名、字段类型和必填项如果返回 HTML 错误页优先考虑网关、代理、URL、Method 或协议层问题。2. 确认请求 Method 和 Endpoint 是否匹配很多 400 并不是 JSON 写错而是请求方法或接口地址不符合接口文档。常见接口文档通常会明确写出GET /users/{id} POST /users PUT /users/{id} PATCH /users/{id} DELETE /users/{id}调试时需要确认GET、POST、PUT、PATCH、DELETE是否用对Endpoint 路径是否正确Path 参数是否放在 URL 路径中Query 参数是否拼在 URL 后Body 参数是否放在请求体中。例如接口要求GET /users/{id}正确请求可能是GET /users/123如果你写成GET /users?id123就可能导致路由匹配不上或者接口认为缺少路径参数。3. 区分 Query、Path 和 Body 参数接口参数常见位置有三种Query、Path和Body。参数位置放错是 API 返回 400 的高频原因。3.1 Query 参数Query 参数放在 URL 后面GET /users?id123statusactive如果接口文档写的是 query 参数就不要把它们放进 JSON Body 里。例如文档要求GET /users?id123就不要写成GET /users { id: 123 }后端如果只从 query 中读取id放到 Body 里它可能根本收不到。3.2 Path 参数Path 参数是 URL 路径的一部分GET /users/123这里的123通常就是用户 ID。接口文档常写成GET /users/{id}对应请求应是GET /users/123而不是GET /users?id1233.3 Body 参数Body 参数常见于POST、PUT、PATCH请求。例如创建用户接口POST /users Content-Type: application/json { name: Alice, age: 20 }新手常见错误是接口要求 JSON Body却把参数拼到 URL 后面。错误示例POST /users?nameAliceage20更常见的正确写法是POST /users Content-Type: application/json { name: Alice, age: 20 }反过来也一样如果接口要求 query 参数你却放进 Body后端也可能读取不到。4. 检查 Headers重点看 Content-Type调 JSON API 时Content-Type非常关键。它的作用是告诉服务器我这次发过去的 Body 是什么格式。如果发送 JSON请求头通常应该是Content-Type: application/jsonBody 示例{ name: Alice, age: 20 }如果是普通表单常见请求头是Content-Type: application/x-www-form-urlencodedBody 可能是nameAliceage20如果是文件上传常见请求头是Content-Type: multipart/form-data最容易出问题的是 Header 和 Body 不一致。例如Content-Type: application/json nameAliceage20请求头告诉服务器“我发的是 JSON”但实际 Body 是表单字符串。后端按 JSON 解析时就可能直接返回 400。5. 不要混淆 Content-Type 和 Accept调接口时经常会看到两个 HeaderContent-Type: application/json Accept: application/json它们含义不同Header含义Content-Type当前请求发送给服务器的内容格式Accept客户端希望服务器返回的内容格式简单理解Content-Type我发给你的是什么 Accept我希望你返回什么排查 JSON 请求 400 时优先看Content-Type是否正确。6. 确认 Body 是否为空如果接口要求请求体但实际发送时 Body 为空后端可能返回Required request body is missing例如接口要求POST /users Content-Type: application/json { name: Alice, age: 20 }但实际请求是POST /users Content-Type: application/json没有 Body就可能触发 400。这类问题在以下场景中很常见前端代码没有正确传body请求库配置写错拦截器把请求体清空了Postman / Apifox Body 类型选错参数本来在代码里有但最终没有序列化发送出去。7. 校验 JSON 语法是否合法JSON 语法比 JavaScript 对象字面量更严格。不是“看起来像对象”就一定是合法 JSON。7.1 key 必须使用双引号错误写法{ name: Alice, age: 20 }正确写法{ name: Alice, age: 20 }7.2 字符串必须使用双引号错误写法{ name: Alice }正确写法{ name: Alice }JSON 中字符串不能使用单引号。7.3 最后一项后面不能多逗号错误写法{ name: Alice, age: 20, }正确写法{ name: Alice, age: 20 }7.4 JSON 中不能写注释错误写法{ name: Alice, // 用户名 age: 20 }正确写法{ name: Alice, age: 20 }7.5 对象和数组必须闭合错误写法{ ids: [1, 2, 3 }正确写法{ ids: [1, 2, 3] }如果不确定 JSON 是否合法可以先复制到 JSON 校验工具中检查。只有语法合法后再继续排查接口字段问题。8. JSON 合法不代表接口一定接受这是调接口时必须注意的一点JSON 合法只代表服务器能解析它不代表接口业务参数一定符合要求。例如{ age: 18 }这段 JSON 是合法的。但如果接口文档要求age是数字类型那么18这种字符串就可能导致后端类型转换失败。正确写法通常应该是{ age: 18 }常见的接口参数问题包括必填字段没传字段名拼错字段大小写不一致字段类型不对枚举值不在允许范围内日期格式不符合要求数组结构不符合文档嵌套对象层级传错。9. 对照接口文档检查字段名字段名必须和接口文档保持一致。例如你传的是{ user_name: Alice }但接口要求的是{ userName: Alice }那么后端可能无法绑定字段进而返回参数错误。大小写也需要注意userId userid userID对很多后端框架来说这可能是三个不同字段不一定会自动匹配。10. 检查字段类型数字、字符串、布尔值不要混用10.1 数字不要误传成字符串可能有问题的写法{ name: Alice, age: 20 }如果接口要求age是数字应写成{ name: Alice, age: 20 }10.2 布尔值不要误传成字符串可能有问题的写法{ enabled: true }正确写法{ enabled: true }JSON 中布尔值是true和false不是true和false加了引号之后它就变成字符串了。11. 区分 null、空字符串和空数组下面几种写法看起来都像“没有内容”但语义不同{ nickname: null }{ nickname: }{ tags: [] }含义分别是写法含义null明确表示没有值空字符串[]空数组如果接口要求非空字符串传null或都可能触发 400。这类问题常见于注册接口用户资料编辑搜索筛选表单提交配置类接口。12. 数组参数确认接口要求哪种传法数组是 API 400 的高频原因因为不同接口约定可能不同。12.1 JSON 数组有的接口要求 Body 中传 JSON 数组{ ids: [1, 2, 3] }如果你写成字符串{ ids: 1,2,3 }就可能导致类型不匹配。12.2 Query 重复参数有的接口要求这样传GET /users?ids1ids2ids312.3 Query 逗号分隔也有接口可能要求GET /users?ids1,2,3这几种写法都可能存在但不能随意混用。必须以接口文档为准。13. 嵌套对象结构必须和文档一致假设接口要求{ user: { name: Alice, address: { city: Shanghai } } }但你传成{ name: Alice, city: Shanghai }这虽然是合法 JSON但结构已经完全不同。后端如果按文档结构绑定字段可能会读取user.name user.address.city而你传的是顶层字段name city这样就可能导致缺少字段或参数绑定失败。14. 日期格式不要凭感觉写日期字段也很容易触发 400。常见格式可能是日期字符串{ birthday: 2024-06-01 }也可能是 ISO 时间{ createdAt: 2024-06-01T10:30:00Z }还有可能是时间戳{ timestamp: 1717218600000 }尤其要注意时间戳单位1717218600 秒级时间戳 1717218600000 毫秒级时间戳它们不是一个意思。日期字段建议严格按照接口文档传不要自己猜格式。15. 使用浏览器 Network 查看真实请求很多时候代码里看着没问题但实际发出去的请求并不是你以为的样子。如果是前端页面调接口可以打开浏览器开发者工具进入 Network 面板重点看Request URL请求地址是否正确Request Method请求方法是否正确Request HeadersContent-Type是否正确Payload实际发送的请求体是什么Response后端返回的具体错误信息。尤其要看Payload。有些问题不是代码表面能看出来的而是请求在发送前经过了序列化参数拼接请求拦截器代理转发封装库处理。最终发出去的内容可能和你代码里的对象不一样。16. 使用 Postman / Apifox 检查 Body 类型使用接口调试工具时可以重点检查Body 是否选择了raw格式是否选择了JSON是否设置了Content-Type: application/json实际发送内容是否和文档示例一致Query、Path、Body 参数是否放对位置。常见错误是 Body 类型选错。例如接口要求 JSON但你选择了x-www-form-urlencoded或form-data后端按 JSON 解析时就可能返回 400。17. 用 cURL 构造最小可复现请求排查复杂问题时建议用 cURL 构造一个最小请求。例如curl -X POST https://api.example.com/users \ -H Content-Type: application/json \ -d {name:Alice,age:20}如果 cURL 请求成功但你的代码一直返回 400说明接口本身大概率可用问题可能出在代码中的 Header 配置Body 序列化参数组装请求拦截器代理层实际发送内容和预期不一致。如果 cURL 也返回 400就继续对照接口文档检查 Method、Endpoint、Headers、Body 和字段规则。18. 前端 fetch 常见坑忘记 JSON.stringify使用fetch发送 JSON 请求时一个典型错误是直接把对象放进body。错误写法const user { name: Alice, age: 20 }; fetch(/api/users, { method: POST, headers: { Content-Type: application/json }, body: user });更常见的正确写法是const user { name: Alice, age: 20 }; fetch(/api/users, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify(user) });关键不是变量在代码里是什么类型而是最终发出去的请求体是什么。有些请求库会自动处理 JSON有些场景需要手动序列化。调试时以 Network 面板看到的真实请求为准。19. 400 可能不是业务接口返回的并不是所有 400 都来自业务代码。有些请求可能在进入业务接口之前就被以下组件拦截网关代理Web 服务器WAFHTTP 协议校验路由层。常见原因包括请求方法不允许URL 中特殊字符没有编码GET 请求带了异常 BodyContent-Length异常请求头太大Cookie 太大请求体太大网关认为请求不合法返回的是 HTML 错误页而不是接口约定的 JSON 错误体。如果你看到的是 HTML 形式的 400 页面而不是接口平时返回的 JSON 结构就要考虑请求可能没有到达业务 API。20. 常见 400 错误信息对照表错误信息可能原因优先检查Invalid JSONJSON 语法错误引号、逗号、括号、注释Unexpected tokenBody 不是合法 JSON是否传了对象、HTML、空字符串或错误格式Required request body is missing请求体缺失Body 是否为空参数是否放错位置Missing required parameter缺少必填参数Query、Path、Body 中的必填项Missing required fieldJSON 缺少字段接口文档中的必填字段type mismatch字段类型不匹配数字、字符串、布尔值、数组类型Cannot deserialize value后端反序列化失败字段类型、日期格式、嵌套结构Content-Type not supported请求头不匹配是否设置了application/jsonRequest header is too large请求头过大Cookie、Token、Header 是否异常400 Bad Request且返回 HTML可能被网关或协议层拦截URL、Method、GET Body、请求头是否合法21. API 400 JSON 请求排查清单遇到接口返回 400可以按下面顺序检查[ ] 响应体里有没有更具体的错误信息 [ ] 请求 Method 是否和接口文档一致 [ ] Endpoint / URL 是否正确 [ ] Path 参数是否放在路径中 [ ] Query 参数是否放在 URL 后 [ ] Body 参数是否放在请求体中 [ ] URL 中特殊字符是否需要编码 [ ] 是否设置 Content-Type: application/json [ ] Body 是否为空 [ ] Body 是否是真正的 JSON 字符串 [ ] JSON 是否能通过语法校验 [ ] 字段名是否和接口文档一致 [ ] 字段大小写是否正确 [ ] 必填字段是否都传了 [ ] 字段类型是否正确 [ ] 数组格式是否符合文档要求 [ ] 嵌套对象结构是否正确 [ ] 日期格式是否符合接口约定 [ ] 枚举值是否在允许范围内 [ ] 是否看过浏览器 Network 中的真实请求 [ ] 是否用 Postman / Apifox 核对过 Body 类型 [ ] 是否用 cURL 构造过最小可复现请求 [ ] 如果返回 HTML 400是否考虑网关、代理或协议层问题 [ ] 如果有后端权限是否查看过服务端日志总结400 Bad Request不应该简单理解为“参数值写错了”。更准确地说它表示这次请求没有满足服务器对格式、参数或协议的要求。推荐排查顺序是先看响应体找具体错误信息检查 Method、Endpoint 和参数位置确认 Headers尤其是Content-Type检查 Body 是否为空是否是合法 JSON对照接口文档检查字段名、字段类型和必填项重点检查数组、嵌套对象、日期、枚举值如果返回 HTML 400考虑网关、代理或协议层问题。记住两个关键点JSON 合法不代表接口一定接受。 接口参数看起来没问题也不代表请求格式一定正确。调 API 时把 Method、URL、Headers、Body 和字段规则放在一起检查通常才能更快定位真正的 400 原因。