JSON.parse返回字符串而不是对象

时间:2017-02-27 20:08:01

标签: javascript json websocket

我写了一个websocket客户端,我希望以json字符串的形式接收消息。为此,我需要登录。如果登录不正确,我发送一个带有nosuccess的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服务器是一个jetty Server,它在json中使用gson.toJson(class)Gson在json中发送一个字符串和一个字符串数组。 Class是一个包含String动作和String数组args的类。

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呢?

3 个答案:

答案 0 :(得分:13)

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

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

答案 1 :(得分:1)

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

var stringResponse = '{"action":"login","args":["nosuccess"]}';

var objResponse = JSON.parse(stringResponse);

console.log(objResponse.args);

您还可以试用上面的代码here

至于为什么服务器在您真正想要一个对象时返回一个字符串,这实际上归结为您的后端代码,您正在使用的库以及传输协议。如果您只想使用前端代码,请使用 JSON.parse 。如果您想编辑后端的响应方式,请提供更多信息。

答案 2 :(得分:0)

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

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

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