Angular向NodeJS发POST请求报JSON位置0意外标记解析错误
问题原因
你遇到的两个异常本质是Angular HttpClient 序列化逻辑和Express body-parser 解析规则不匹配导致的,对应两个场景的问题:
- 不调用
JSON.stringify直接传字符串this.keyword时:HttpClient检测到请求体是原始字符串类型,会自动把Content-Type设为text/plain,而你后端的bodyParser.json()只会解析Content-Type为application/json的请求,不会处理文本类型请求体,自然拿到的req.body是undefined。 - 手动调用
JSON.stringify(this.keyword)时报JSON解析错误:假设你输入的关键词是test,JSON.stringify("test")会得到带双引号包裹的字符串"test",此时你手动强制设置Content-Type: application/json,但HttpClient不会对已经是字符串类型的请求体做二次校验和格式修正,实际发出去的请求体存在引号转义偏差,body-parser解析时第一个读到的字符就是多余的双引号,直接触发Unexpected token " in JSON at position 0报错。 - 额外隐患:你当前Express服务的CORS中间件注册在
body-parser之后,也没有单独处理OPTIONS预检请求,后续很容易触发跨域拦截问题。
修复步骤
1. 调整Angular端请求代码
HttpClient本身内置了JSON序列化能力,只要你传的请求体是普通对象,它会自动完成序列化、自动设置正确的Content-Type请求头,不需要你手动调用JSON.stringify、也不需要手动设置Content-Type:
export class SearchComponent { constructor(private http: HttpClient) {} newWord = ''; keyword = ''; onClick() { const headers = new HttpHeaders() .set('Authorization', 'my-auth-token'); // 直接传对象参数,不要手动做JSON序列化 this.http .post('http://localhost:3000/search', { keyword: this.keyword }, { responseType: 'text', headers: headers }) .subscribe((data) => { this.newWord = data; }); } }
2. 调整Express端代码顺序
CORS相关的响应头配置必须放在所有中间件、路由注册之前,同时单独处理OPTIONS预检请求,避免跨域异常:
const bodyParser = require("body-parser"); const express = require("express"); const app = express(); // CORS配置移到最顶部 app.all("/*", function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS"); res.header( "Access-Control-Allow-Headers", "Content-Type, Authorization, Content-Length, X-Requested-With" ); // 预检请求直接返回200,不需要往下走解析逻辑 if (req.method === "OPTIONS") { return res.sendStatus(200); } next(); }); // CORS配置完成后再注册bodyParser app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.listen(3000, () => { console.log("Server is running on port 3000"); }); app.post("/search", (req, res) => { // 此时req.body就是前端传的 { keyword: "你输入的内容" } 格式 console.log("接收到的参数:", req.body); res.send(req.body.keyword); });
修改完成后重启Node服务,再触发请求就可以正常传参、接收返回,不会再出现JSON解析报错或者req.body为undefined的问题。
内容的提问来源于stack exchange,提问作者OutOfBounds
相关产品推荐
相关产品推荐

