发送含特殊字符的POST请求时出现JSON语法错误,原因是什么?
首先得澄清一个关键误区:你遇到的SyntaxError: Unexpected token < in JSON at position 0错误,根本不是因为JSON里的特殊字符(长破折号–、右单引号’)不合法——JSON完全支持Unicode字符,只要处理流程正确就不会出问题。这个错误的真实原因是:服务器返回了HTML格式的错误响应(比如400 Bad Request的错误页面),而你的代码尝试把这份HTML当成JSON来解析,HTML的第一个字符通常是<,所以才触发了这个报错。
接下来看你的代码里的几个核心问题,正是这些问题导致服务器无法正确处理请求,最终返回错误页面:
1. 手动设置Content-Length的逻辑完全错误
你代码里的Content-Length是用JSON.stringify(body).length计算的,但实际发送的请求体却是硬编码的JSON.stringify({ "text": "..." })——这两个内容完全不匹配!如果调用postScriptRequest时传入的body和硬编码对象不一样,计算出的长度就会和实际请求体长度不符,服务器收到后无法正确解析请求体,直接返回错误页面。
解决办法:删掉手动设置的Content-Length头——request库会自动帮你计算并设置正确的Content-Length,完全不需要手动处理。
2. 缺少Content-Type: application/json请求头
服务器需要明确知道你发送的是JSON格式的请求体,否则它可能会用错误的规则解析(比如当成表单数据),导致解析失败返回错误。
解决办法:在headers里添加'Content-Type': 'application/json'。
3. 硬编码请求体与传入参数逻辑冲突(示例代码问题)
你的示例里硬写了请求体内容,但函数参数是body,这会导致实际调用时即便传入body,请求体还是用的硬编码内容,完全不符合函数设计的预期。应该把硬编码部分替换成传入的body参数。
修复后的完整代码
import request from 'request'; export default { postScriptRequest(body) { return new Promise((resolve, reject) => { const options = { method: 'post', body: JSON.stringify(body), // 使用传入的body参数,符合函数逻辑 headers: { 'Content-Type': 'application/json' // 告诉服务器请求体是JSON格式 // 移除手动设置的Content-Length,request会自动处理 }, url: 'my-url.com' }; request(options, (error, response, responseBody) => { // 先处理请求本身的错误(比如网络问题) if (error) { reject(error); return; } if (response.statusCode === 200) { // 建议额外加一层JSON解析,确保返回的内容是合法JSON try { const parsedData = JSON.parse(responseBody); resolve(parsedData); } catch (parseError) { reject(parseError); } } else { // 把响应体也返回,方便排查服务器到底返回了什么错误内容 reject({ statusCode: response.statusCode, errorContent: responseBody }); } }); }); } };
关于特殊字符的补充说明
长破折号–(U+2013)和右单引号’(U+2019)都是合法的Unicode字符,JSON.stringify会自动正确处理它们,不需要额外转义。只要你的请求是UTF-8编码(request默认就是UTF-8),且服务器能正确处理UTF-8格式的JSON,这些字符不会引发任何问题。
调试时建议把服务器返回的responseBody打印出来,你大概率会看到服务器返回的错误提示HTML,这能帮你更精准地定位服务器拒绝请求的具体原因。
内容的提问来源于stack exchange,提问作者Valip




