web-dev-qa-db-fra.com

Comment tester si une chaîne est JSON ou non?

J'ai un simple appel AJAX et le serveur renvoie soit une chaîne JSON avec des données utiles, soit une chaîne de message d'erreur générée par la fonction PHP mysql_error(). Comment puis-je tester si ces données sont une chaîne JSON ou le message d'erreur. 

Ce serait bien d'utiliser une fonction appelée isJSON comme vous pouvez utiliser la fonction instanceof pour tester si quelque chose est un tableau.

C'est ce que je veux:

if (isJSON(data)){
    //do some data stuff
}else{
    //report the error
    alert(data);
}
116
jeffery_the_wind

Utilisez JSON.parse

function isJson(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}
232
Bourne

Ce code est JSON.parse(1234) ou JSON.parse(0) ou JSON.parse(false) ou JSON.parse(null) tous renverront true.

function isJson(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

J'ai donc réécrit le code de cette façon:

function isJson(item) {
    item = typeof item !== "string"
        ? JSON.stringify(item)
        : item;

    try {
        item = JSON.parse(item);
    } catch (e) {
        return false;
    }

    if (typeof item === "object" && item !== null) {
        return true;
    }

    return false;
}

Résultat du test:

Résultat du test isJson

42
kubosho_

Si le serveur répond avec JSON, il aura un type de contenu application/json, s'il répond avec un message en texte brut, il doit alors avoir un type de contenu text/plain. Assurez-vous que le serveur répond avec le type de contenu correct et testez-le.

21
Quentin

lorsque vous utilisez jQuery $.ajax(), la réponse aura la propriété responseJSON si la réponse était JSON, vous pouvez le vérifier comme suit:

if (xhr.hasOwnProperty('responseJSON')) {}
10
rémy

J'aime la meilleure réponse, mais si c'est une chaîne vide, elle retourne true. Alors voici un correctif:

function isJSON(MyTestStr){
    try {
        var MyJSON = JSON.stringify(MyTestStr);
        var json = JSON.parse(MyJSON);
        if(typeof(MyTestStr) == 'string')
            if(MyTestStr.length == 0)
                return false;
    }
    catch(e){
        return false;
    }
    return true;
}
6
Lonnie Price Sr.

Eh bien ... Cela dépend de la manière dont vous recevez vos données. Je pense que le serveur répond avec une chaîne Formatée JSON (à l'aide de json_encode () en PHP, par exemple). Si vous utilisez la publication JQuery et définissez les données de réponse sur un format JSON et que ce soit un JSON mal formé, cela produira une erreur:

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        //Supposing x is a JSON property...
        alert(response.x);

  },
  dataType: 'json',
  //Invalid JSON
  error: function (){ alert("error!"); }
});

Toutefois, si vous utilisez la réponse de type sous forme de texte, vous devez utiliser $ .parseJSON. Selon le site jQuery: "Le passage d'une chaîne JSON mal formée peut entraîner la génération d'une exception". Ainsi, votre code sera:

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        try {
            parsedData = JSON.parse(response);
        } catch (e) {
            // is not a valid JSON string
        }

  },
  dataType: 'text',
});
5
Lucas Batistussi

Il existe probablement des tests que vous pouvez faire. Par exemple, si vous savez que le code JSON renvoyé sera toujours entouré de { et de }, vous pouvez tester ces caractères ou une autre méthode de hacky. Ou vous pouvez utiliser la bibliothèque json.org JS pour essayer de l'analyser et de vérifier si elle réussit.

Je suggérerais cependant une approche différente. Votre script PHP renvoie actuellement JSON si l'appel aboutit, mais quelque chose d'autre si ce n'est pas le cas. Pourquoi ne pas toujours renvoyer JSON?

Par exemple.

Appel réussi:

{ "status": "success", "data": [ <your data here> ] }

Appel erroné:

{ "status": "error", "error": "Database not found" }

Cela faciliterait beaucoup l'écriture de votre côté client JS - tout ce que vous avez à faire est de vérifier le membre "statut" et l'acte en conséquence.

4
mdm
var parsedData;

try {
    parsedData = JSON.parse(data)
} catch (e) {
    // is not a valid JSON string
}

Cependant, je vous suggérerai que votre appel/service http devrait toujours renvoyer des données au même format. Donc, si vous avez une erreur, vous devriez avoir un objet JSON qui enveloppe cette erreur:

{"error" : { "code" : 123, "message" : "Foo not supported" } } 

Et peut-être utiliser comme code HTTP un code 5xx.

3
ZER0

J'utilise seulement 2 lignes pour effectuer cela:

var isValidJSON = true;
try { JSON.parse(jsonString) } catch { isValidJSON = false }

C'est tout!

Mais gardez à l'esprit qu'il y a 2 pièges:
1. JSON.parse(null) renvoie null
2. Tout nombre ou chaîne peut être analysé avec la méthode JSON.parse().
JSON.parse("5") renvoie 5 
JSON.parse(5) renvoie 5 

Jouons sur le code:

// TEST 1
var data = '{ "a": 1 }'

// Avoiding 'null' trap! Null is confirmed as JSON.
var isValidJSON = data ? true : false
try { JSON.parse(data) } catch(e) { isValidJSON = false }

console.log("data isValidJSON: ", isValidJSON);
console.log("data isJSONArray: ", isValidJSON && JSON.parse(data).length ? true : false);

Console outputs:
data isValidJSON:  true
data isJSONArray:  false


// TEST 2
var data2 = '[{ "b": 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data2) } catch(e) { isValidJSON = false }

console.log("data2 isValidJSON: ", isValidJSON);
console.log("data2 isJSONArray: ", isValidJSON && JSON.parse(data2).length ? true : false);

Console outputs:
data2 isValidJSON:  true
data2 isJSONArray:  true


// TEST 3
var data3 = '[{ 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data3) } catch(e) { isValidJSON = false }

console.log("data3 isValidJSON: ", isValidJSON);
console.log("data3 isJSONArray: ", isValidJSON && JSON.parse(data3).length ? true : false);

Console outputs:
data3 isValidJSON:  false
data3 isJSONArray:  false


// TEST 4
var data4 = '2'

var isValidJSON = data ? true : false
try { JSON.parse(data4) } catch(e) { isValidJSON = false }

console.log("data4 isValidJSON: ", isValidJSON);
console.log("data4 isJSONArray: ", isValidJSON && JSON.parse(data4).length ? true : false);


Console outputs:
data4 isValidJSON:  true
data4 isJSONArray:  false


// TEST 5
var data5 = ''

var isValidJSON = data ? true : false
try { JSON.parse(data5) } catch(e) { isValidJSON = false }

console.log("data5 isValidJSON: ", isValidJSON);
console.log("data5 isJSONArray: ", isValidJSON && JSON.parse(data5).length ? true : false);


Console outputs:
data5 isValidJSON:  false
data5 isJSONArray:  false

// TEST 6
var data6; // undefined

var isValidJSON = data ? true : false
try { JSON.parse(data6) } catch(e) { isValidJSON = false }

console.log("data6 isValidJSON: ", isValidJSON);
console.log("data6 isJSONArray: ", isValidJSON && JSON.parse(data6).length ? true : false);

Console outputs:
data6 isValidJSON:  false
data6 isJSONArray:  false
2
efkan

Vous pouvez essayer de le décoder et d’attraper l’exception exception (native ou json2.js ):

try {
  newObj = JSON.parse(myJsonString);
} catch (e) {
  console.log('Not JSON');
}

Cependant, je suggérerais de toujours rendre la réponse valide en JSON. Si votre requête MySQL vous renvoie une erreur, il vous suffit de renvoyer JSON avec l’erreur suivante:

{"error":"The MySQL error string."}

Et alors:

if (myParsedJSON.error) {
  console.log('An error occurred: ' + myParsedJSON.error);
}
2
James Sumners

Toutes les chaînes json commencent par '{' ou '[' et se terminent par le '}' ou ']' correspondant, alors vérifiez-le. 

Voici comment Angular.js le fait:

var JSON_START = /^\[|^\{(?!\{)/;
var JSON_ENDS = {
  '[': /]$/,
  '{': /}$/
};

function isJsonLike(str) {
    var jsonStart = str.match(JSON_START);
    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
}

https://github.com/angular/angular.js/blob/v1.6.x/src/ng/http.js

0
carlin.scott

Je suggère en mode TypeScript:

export function stringify(data: any): string {
    try {
         return JSON.stringify(data)
    } catch (e) {
         return 'NOT_STRINGIFIABLE!'
    }
}
0
Mahyar SEPEHR