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

Nig*_*ewe 21 javascript json websocket

我正在写一个websocket客户端,我想收到消息作为json字符串.为此,我需要登录.如果登录不正确,我发送一个带有nosuccess的json字符串.JSON字符串:

{"action":"login","args":["nosuccess"]}
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)

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

evt.data返回:

 "{\"action\":\"login\",\"args\":[\"nosuccess\"]}"
Run Code Online (Sandbox Code Playgroud)

数据返回:

 {"action":"login","args":["nosuccess"]}
Run Code Online (Sandbox Code Playgroud)

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));
}
Run Code Online (Sandbox Code Playgroud)

如果我更改此行:

 var data = JSON.parse(evt.data);
Run Code Online (Sandbox Code Playgroud)

对此:

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

然后它是一个json对象,但是当我使用evt.data时它就是一个字符串.如果我将行更改为:

    var data = JSON.parse(JSON.parse(evt.data));
Run Code Online (Sandbox Code Playgroud)

然后它工作,但为什么,通常它应该只用一个JSON.parse,它应该吗?

小智 17

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

如果你没有字符串化你的字符串,它将转换为一个对象,通常没有必要,但如果你无法控制获得的值,那么运行JSON.parse()两次就可以了.


Mad*_*hur 14

@DerpSuperleggera 是正确的。问题确实是字符串过度字符串化

let arr = "[\"~#iM\",[\"is_logged_out_token\",false,\"token_type\",\"Bearer\"]]"
Run Code Online (Sandbox Code Playgroud)

因此,为了将其解析为对象,我只运行了JSON.parse两次,就成功了!

let obj = JSON.parse(JSON.parse(arr))
Run Code Online (Sandbox Code Playgroud)


小智 7

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

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

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

Run Code Online (Sandbox Code Playgroud)