简体   繁体   English

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

[英]JSON.parse returns string instead of object

im writing a websocket client and i would like to receive messages as json strings.我正在编写一个 websocket 客户端,我想以 json 字符串的形式接收消息。 For this I need a login.为此,我需要登录。 And if the login isn't true i send a json string with nosuccess.如果登录不正确,我会发送一个没有成功的 json 字符串。 JSON String: JSON 字符串:

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

On the client I'm using this to get the string:在客户端上,我使用它来获取字符串:

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);

But the type of data is a string... But why?但是数据的类型是字符串......但为什么呢?

evt.data returns: evt.data 返回:

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

data returns:数据返回:

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

The WebSocket server is a jetty Server which sends a string and a string array in json parsed in json with gson.toJson(class) Gson by Google. WebSocket 服务器是一个 jetty 服务器,它发送一个字符串和一个字符串数组,在 json 中解析为 json 和 gson.toJson(class) Gson by Google。 The Class is a class containing String action and String array args. Class 是一个包含字符串操作和字符串数组参数的类。

Complete source code of websocket.js: 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));
}

If I change this line:如果我改变这一行:

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

to this:对此:

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

Then it is a json object, but when I use evt.data then it is a string.然后它是一个 json 对象,但是当我使用 evt.data 时它是一个字符串。 If I change the line to this:如果我将行更改为:

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

Then it works, but why, normally it should do it with only one JSON.parse, should it?然后它就可以工作了,但是为什么,通常它应该只用一个 JSON.parse 来完成,是吗?

This seems to be fairly consistent with over -stringified strings.这似乎与过度字符串化的字符串相当一致。 For example I loaded a text file using FileReader.readAsText that came with \\n and \\r which rendered in the console, so I did - (JSON.stringify(reader.result)).replace(/(?:\\\\[rn])+/g, '') first to see the symbols, then to get rid of them.例如,我使用FileReader.readAsText加载了一个文本文件,它带有在控制台中呈现的\\n\\r ,所以我做了 - (JSON.stringify(reader.result)).replace(/(?:\\\\[rn])+/g, '')首先查看符号,然后去掉它们。 Taking that and running JSON.parse() on it converts it to a non-escaped string, so running JSON.parse() again creates an object.接受它并在其上运行JSON.parse()会将其转换为非转义字符串,因此再次运行JSON.parse()会创建一个对象。

If you do not stringify your string, it will convert to an object and often it is not necessary but if you have no control over the obtained value, then running JSON.parse() twice will do the trick.如果您不字符串化您的字符串,它将转换为一个对象,通常没有必要,但如果您无法控制获得的值,那么运行JSON.parse()两次就可以了。

As others have stated in the comments it seems that this issue has been solved.正如其他人在评论中所说的那样,这个问题似乎已经解决了。 If you are receiving a response from the server as a "stringified object" then you can turn it into a normal object with JSON.parse() like so:如果您从服务器接收响应作为“字符串化对象”,那么您可以使用JSON.parse()将其转换为普通对象,如下所示:

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

var objResponse = JSON.parse(stringResponse);

console.log(objResponse.args);

You can also try out the above code here .您也可以在此处尝试上述代码。

As for why the server is returning a string when you really wanted an object, that really comes down to your backend code, what library you are using, and the transport protocol.至于为什么当您真正想要一个对象时服务器会返回一个字符串,这实际上归结为您的后端代码、您使用的库以及传输协议。 If you just want your front-end code to work, use JSON.parse .如果您只想让前端代码正常工作,请使用JSON.parse If you want to edit how the backend responds, please provide more information.如果您想编辑后端的响应方式,请提供更多信息。

The checked response is correct in that it seems to be an issue of over-stringified strings.检查的响应是正确的,因为它似乎是字符串过度字符串化的问题。 I came across it from using AWS Amplify AWSJSON type in my project.我在我的项目中使用 AWS Amplify AWSJSON 类型时遇到了它。 The solution that worked for me was to iterate multiple (twice) to get an object.对我有用的解决方案是迭代多个(两次)以获取一个对象。

Wrote a simple JS function that when used to parse will return an object.编写了一个简单的 JS 函数,用于解析时将返回一个对象。 There isn't really error checking, but a starting point.没有真正的错误检查,而是一个起点。

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

@DerpSuperleggera is correct. @DerpSuperleggera 是正确的。 The issue was indeed an over -stringified string问题确实是一个过度字符串化的字符串

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

So to parse it as an object, I just ran it through JSON.parse twice and that did the trick!所以要将它解析为一个对象,我只是通过JSON.parse运行它两次,就成功了!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM