web-dev-qa-db-fra.com

JSON.parse renvoie une chaîne au lieu d'un objet

im écrivant un client websocket et je voudrais recevoir des messages sous forme de chaînes json. Pour cela, j'ai besoin d'un identifiant. Et si la connexion n'est pas vraie, j'envoie une chaîne json avec nosuccess. Chaîne JSON:

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

Sur le client, j'utilise ceci pour obtenir la chaîne:

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

Mais le type de données est une chaîne ... Mais pourquoi?

evt.data renvoie:

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

retours de données:

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

Le serveur WebSocket est un serveur de jetée qui envoie une chaîne et un tableau de chaînes en json analysé en json avec gson.toJson (classe) Gson par Google. La classe est une classe contenant des arguments d'action de chaîne et de tableau de chaînes.

Code source complet de 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));
}

Si je change cette ligne:

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

pour ça:

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

Ensuite, c'est un objet json, mais lorsque j'utilise evt.data, c'est une chaîne. Si je change la ligne en ceci:

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

Ensuite, cela fonctionne, mais pourquoi, normalement, il devrait le faire avec un seul JSON.parse, devrait-il?

21
Nightloewe

Cela semble être assez cohérent avec over - chaînes stringifiées. Par exemple, j'ai chargé un fichier texte à l'aide de FileReader.readAsText Fourni avec \n Et \r Qui a été rendu dans la console, alors j'ai fait - (JSON.stringify(reader.result)).replace(/(?:\\[rn])+/g, '') D'abord pour voir le symboles, puis de s'en débarrasser. En prenant cela et en exécutant JSON.parse() dessus, il le convertit en une chaîne non échappée, donc exécuter JSON.parse() crée à nouveau un objet.

Si vous ne stringifiez pas votre chaîne, elle se convertira en objet et souvent ce n'est pas nécessaire mais si vous n'avez aucun contrôle sur la valeur obtenue, alors exécuter deux fois JSON.parse() fera l'affaire.

15
DerpSuperleggera

Comme d'autres l'ont indiqué dans les commentaires, il semble que ce problème ait été résolu. Si vous recevez une réponse du serveur en tant qu '"objet stringifié", vous pouvez le transformer en un objet normal avec JSON.parse () comme ceci :

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

var objResponse = JSON.parse(stringResponse);

console.log(objResponse.args);

Vous pouvez également essayer le code ci-dessus ici .

Quant à savoir pourquoi le serveur renvoie une chaîne lorsque vous vouliez vraiment un objet, cela se résume vraiment à votre code backend, à la bibliothèque que vous utilisez et au protocole de transport. Si vous voulez juste que votre code frontal fonctionne, utilisez JSON.parse . Si vous souhaitez modifier la réponse du backend, veuillez fournir plus d'informations.

1
Jim