Ubuntu下用curl向Node.js应用POST JSON出现语法错误如何解决?
问题原因拆解
咱们一步步理清你遇到的问题:
第一个JSON格式curl命令出错
你最初用双引号包裹JSON并转义内部引号的写法,在bash环境下可能因为shell的解析规则,导致实际发送的JSON内容出现异常(比如转义失效或多余字符),服务器收到的请求体开头不是预期的{,才触发了SyntaxError: Unexpected token n in JSON at position 1。-d name:'richard'写法的双重错误
这种写法本身不符合curl的-d参数规范(正确表单格式是key=value),而且curl会默认把请求Content-Type设为application/x-www-form-urlencoded,但你的服务器只配置了bodyParser.json()来解析JSON请求体,自然无法识别表单数据,同时curl本身也会因为参数格式不合法报错。改
Content-Type为text/html的假象
当你修改Content-Type后,bodyParser.json()会忽略这个请求(它只处理Content-Type为application/json的请求),此时req.body是空对象。你的代码直接插入空对象到数据库,所以返回了带_id的空文档——这并不是你想要的正确插入数据的结果。
解决方案
1. 正确的curl JSON POST命令
在bash环境下,最稳妥的方式是用单引号包裹JSON内容,避免shell解析干扰,不需要转义内部双引号:
curl -X POST -H "Content-Type: application/json" -d '{"name":"richard","email":"ricard@rublev.co"}' http://localhost:3000/collections/curl-test
如果必须用双引号包裹,确保转义正确且去掉多余空格:
curl -X POST -H "Content-Type: application/json" -d "{\"name\":\"richard\",\"email\":\"ricard@rublev.co\"}" http://localhost:3000/collections/curl-test
2. 可选:让服务器同时支持表单数据
如果你希望服务器既能处理JSON请求,也能接受表单提交,可以在index.js中添加表单解析中间件:
const app = express() // 保留JSON解析 app.use(bodyParser.json()) // 添加表单数据解析(extended: true支持复杂结构) app.use(bodyParser.urlencoded({ extended: true })) // 后续代码不变 app.param('collectionName', (req, res, next, collectionName) => { req.collection = db.collection(collectionName) return next() }) app.post('/collections/:collectionName', (req, res, next) => { req.collection.insert(req.body, {}, (e, results) => { if (e) return next(e) res.send(results.ops) }) })
此时就能用正确的表单格式发送curl请求:
curl -X POST -d "name=richard" -d "email=ricard@rublev.co" http://localhost:3000/collections/curl-test
验证小技巧
你可以在服务器的post路由里打印req.body,确认数据是否正确解析:
app.post('/collections/:collectionName', (req, res, next) => { console.log('Received request body:', req.body) // 新增打印 req.collection.insert(req.body, {}, (e, results) => { if (e) return next(e) res.send(results.ops) }) })
如果控制台输出{ name: 'richard', email: 'ricard@rublev.co' },说明解析成功了。
内容的提问来源于stack exchange,提问作者Richard Rublev

