JSON 字符串上的 JSON 解析抛出“无法将对象转换为原始值”

Posted

技术标签:

【中文标题】JSON 字符串上的 JSON 解析抛出“无法将对象转换为原始值”【英文标题】:JSON parse on a JSON string throws "Cannot convert object to primitive value" 【发布时间】:2018-05-19 05:38:55 【问题描述】:

server.js

使用正文解析器中间件、把手和快递

路线

module.exports = function (app) 
    app.post('/questionnaire/submit', function (req, res)  // Ajax Call
        var data = JSON.parse(req.body);
        res.send();
    );
;

客户

function submitData()  // Send a data object to the server
    $.ajax(
        type: 'POST',
        url: '/questionnaire/submit',
        dataType: "json",
        data: JSON.stringify(
            satisfactory: "text 1",
            improvement: "text 2",
            rating: 0.7
        )
    ).done(function () 
        $(location).attr('href', '/sendOff');
    ).fail(function () 

    );

当记录 req.body 时,我得到一个 JSON 字符串

'"satisfactory":"text 1","improvement":"text 2","rating":0.7': ''

我尝试将此字符串解析为一个对象。当我这样做时,我会收到此错误消息

     TypeError: Cannot convert object to primitive value
     at JSON.parse (<anonymous>)
     at C:\Users\mah\Desktop\FeedbackTool\Server\Routes\questionnaire.js:12:25
     at Layer.handle [as handle_request] (C:\Users\mah\node_modules\express\lib\router\layer.js:95:5)
     at next (C:\Users\mah\node_modules\express\lib\router\route.js:137:13)
     at Route.dispatch (C:\Users\mah\node_modules\express\lib\router\route.js:112:3)
     at Layer.handle [as handle_request] (C:\Users\mah\node_modules\express\lib\router\layer.js:95:5)
     at C:\Users\mah\node_modules\express\lib\router\index.js:281:22
     at Function.process_params (C:\Users\mah\node_modules\express\lib\router\index.js:335:12)
     at next (C:\Users\mah\node_modules\express\lib\router\index.js:275:10)
     at C:\Users\mah\node_modules\body-parser\lib\read.js:130:5

那么如何将字符串解析为对象?

通常我会执行JSON.parse(req.body)

【问题讨论】:

“在记录 req.body 时我得到一个 JSON 字符串” 这对我来说看起来不像 JSON 字符串。它看起来像是带有 JSON 的东西,但开头的 ' 不是 JSON(而且结尾看起来很奇怪)。 @TJCrowder 是 '&lt;json&gt;': '' 形式的字符串,即一个完整的JSON文档作为另一个JSON文档的key,除非在JSON中不能选择使用',所以外部文档无效。 @meagar:属性名称和其他字符串在 JSON 中总是用双引号引起来。 (编辑:啊,你编辑了。:-))而且由于 OP 使用的是JSON.stringify,我们知道它不会有单引号字符串... 【参考方案1】:

dataType 没有说明您发送的数据类型,它说明了您期望的响应类型。您需要在您的ajax 通话中说明您正在通过contentType: "application/json" 发送JSON。 the documentation 中的详细信息。 (到目前为止,你不是第一个或唯一一个被 dataType 命名绊倒的人。)

这是问题的一半。另一半见Stamos' answer。

【讨论】:

【参考方案2】:

由于您使用的是body-parser 中间件,因此您不必再次解析req.body,因为它已经被body-parser 解析了

例子

如果你用过 app.use(bodyParser.json())

那么你只需要这样做

module.exports = function (app) 
    app.post('/questionnaire/submit', function (req, res)  // Ajax Call
        var data = req.body; // this is already parsed and is an object
        res.send();
    );
;

正如@T.J.所指出的。 Crowder 你也应该发送正确的contentType 所以body-parser 知道它的json

function submitData()  // Send a data object to the server
    $.ajax(
        type: 'POST',
        url: '/questionnaire/submit',
        contentType: 'application/json',
        data: JSON.stringify(
            satisfactory: "text 1",
            improvement: "text 2",
            rating: 0.7
        )
    ).done(function () 
        $(location).attr('href', '/sendOff');
    ).fail(function () 

    );

【讨论】:

好点。这是问题的另一半(前半部分是sending the right contentType)。【参考方案3】:

您需要设置正确的 contentType:

$.ajax(
    type: 'POST',
    url: '/questionnaire/submit',
    contentType: 'application/json',
    data: JSON.stringify( satisfactory: "text 1", rating: 0.7 )
);


app.post('/questionnaire/submit', function (req, res)  // Ajax Call
    var data = JSON.parse(req.body);
    console.log(data.rating); // 0.7
    res.send(data);
);

此外,使用body-parser,您可以避免在服务器端调用JSON.parse the link。

【讨论】:

但是我没有提到body-parser中间件...这真的很重要

以上是关于JSON 字符串上的 JSON 解析抛出“无法将对象转换为原始值”的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSJSONSerialization 解析 JSON - 抛出 NSException

parse.JSON()报错是什么原因?

json字符串转对象,遇到空字符串会抛异常吗

为啥 JSON.parse 会抛出跨域错误?

关于json解析的几种方法

关于JSON解析的深坑之BOM头