【问题标题】:JSON.parse returns string instead of objectJSON.parse 返回字符串而不是对象
【发布时间】:2017-07-18 14:26:45
【问题描述】:

我正在编写一个 websocket 客户端,我想以 json 字符串的形式接收消息。为此,我需要登录。如果登录不正确,我会发送一个没有成功的 json 字符串。 JSON字符串:

{"action":"login","args":["nosuccess"]}

在客户端我使用它来获取字符串:

WebSocket socket = new WebSocket("ws://localhost:2555/api");

socket.onmessage = function(evt) {
    console.log(evt.data);
    console.log(typeof(evt.data));
    onMessage(evt);
}
function onMessage(evt) {
var data = JSON.parse(evt.data);
var action = data.action;
var args = data.args;
console.log(data);
console.log(typeof(data));
console.log(action);
console.log(args);

但是数据的类型是字符串... 但为什么呢?

evt.data 返回:

 "{\"action\":\"login\",\"args\":[\"nosuccess\"]}"

数据返回:

 {"action":"login","args":["nosuccess"]}

WebSocket 服务器是一个码头服务器,它在 json 中发送一个字符串和一个字符串数组,用 Google 的 gson.toJson(class) Gson 解析为 json。 Class 是一个包含 String 动作和 String 数组参数的类。

websocket.js的完整源码:

var socket;

function openWebsocket(adress) {
    socket = new WebSocket(adress);
    socket.onopen = function(evt) {
        console.log("Socket opened [" + adress + "]");
    };
    socket.onclose = function(evt) {
        loadPage("login.html");
        console.log("Socket closed [" + evt.code + "]");
    }
    socket.onmessage = function(evt) {
        onMessage(evt);
    }
    socket.onerror = function(evt) {
        console.log("Socket couldn't connect [" + evt.message + "]");
        showMessage("fa-exclamation-circle", "Socket couldn't be established!", 1000);
    }
}

function onMessage(evt) {
    var data = JSON.parse(evt.data);
    var action = data.action;
    var args = data.args;
    console.log(data);
    console.log(typeof(data));
    console.log(action);
    console.log(args);
    $(".card-container h3").html(data);

    if(action == "login") {
        if(args[0] == "success") {
            loadPage("dashboard.htm");
            currentpage = "dashboard.htm";
            showMessage("fa-check", "Du wurdest erfolgreich eingeloggt", 2000);
        } else if(args[0] == "nosuccess") {
            loadPage("login.html");
            currentpage = "login.html";
            showMessage("fa-exclamation-circle", "Falscher Benutzername oder falsches Passwort", 2000);
        } else if(args[0] == "unauthenticated") {
            loadPage("login.html");
            currentpage = "login.html";
            showMessage("fa-exclamation-circle", "Login failure: not authenticated", 2000);
        }
    }

}

function sendMessage(json) {
    $(".card-container h3").html(JSON.stringify(json));
    console.log(JSON.stringify(json));
    socket.send(JSON.stringify(json));
}

如果我改变这一行:

 var data = JSON.parse(evt.data);

到这里:

var data = JSON.parse("{\"action\":\"login\",\"args\":[\"nosuccess\"]}");

那么它是一个 json 对象,但是当我使用 evt.data 时它是一个字符串。 如果我将这一行改为:

    var data = JSON.parse(JSON.parse(evt.data));

那么它可以工作,但是为什么通常它应该只使用一个 JSON.parse 来完成,不是吗?

【问题讨论】:

  • jsbin.com/morutob/1/edit?js,console — 我无法重现该问题。 evt.data的值你肯定搞错了。
  • 如果我在 JSON.parse() 中写入 evt.data 的值;像 JSON.parse("{\"action\":\"login\",\"args\":[\"nosuccess\"]}");手动然后将其解析为对象
  • @Quentin evt.data 是我在帖子中解释的字符串
  • 如果您手动编写它并获取一个对象,但从evt.data 获取它并且不要......那么您手动编写的内容和您从evt.data 获取的内容是不同的 所以你肯定对evt.data的值有误。
  • 我遇到了完全相同的问题,这是一个被字符串化了两次的对象

标签: javascript json websocket


【解决方案1】:

这似乎与 over-stringified 字符串相当一致。例如,我使用FileReader.readAsText 加载了一个文本文件,该文件附带\n\r 在控制台中呈现,所以我做了-(JSON.stringify(reader.result)).replace(/(?:\\[rn])+/g, '') 首先查看符号,然后删除它们。接受它并在其上运行 JSON.parse() 会将其转换为非转义字符串,因此再次运行 JSON.parse() 会创建一个对象。

如果您不对字符串进行字符串化,它将转换为对象,并且通常没有必要,但如果您无法控制获得的值,则运行 JSON.parse() 两次即可。

【讨论】:

    【解决方案2】:

    正如其他人在 cmets 中所说的那样,这个问题似乎已经解决了。如果您从服务器接收作为“字符串化对象”的响应,那么您可以使用 JSON.parse() 将其转换为普通对象,如下所示:

    var stringResponse = '{"action":"login","args":["nosuccess"]}';
    
    var objResponse = JSON.parse(stringResponse);
    
    console.log(objResponse.args);
    

    你也可以试试上面的代码here

    至于为什么当你真正想要一个对象时服务器会返回一个字符串,这实际上取决于你的后端代码、你使用的库以及传输协议。如果您只想让前端代码正常工作,请使用 JSON.parse。如果您想修改后端的响应方式,请提供更多信息。

    【讨论】:

      【解决方案3】:

      检查的响应是正确的,因为它似乎是字符串过度字符串化的问题。我在我的项目中使用 AWS Amplify AWSJSON 类型时遇到了它。对我有用的解决方案是迭代多个(两次)来获取一个对象。

      写了一个简单的JS函数,用来解析时会返回一个对象。没有真正的错误检查,而是一个起点。

          export function jsonParser(blob) {
             let parsed = JSON.parse(blob);
             if (typeof parsed === 'string') parsed = jsonParser(parsed);
             return parsed;
          }
      
      

      【讨论】:

        【解决方案4】:

        @DerpSuperleggera 是正确的。这个问题确实是一个 over-stringified string

        let arr = "[\"~#iM\",[\"is_logged_out_token\",false,\"token_type\",\"Bearer\"]]"
        

        所以为了将它解析为一个对象,我只是通过JSON.parse 运行了两次,就成功了!

        let obj = JSON.parse(JSON.parse(arr))
        

        【讨论】:

          猜你喜欢
          • 2011-09-20
          • 2011-07-29
          • 2012-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多