Transformer en toute sécurité une chaîne JSON en objet


1336

Étant donné une chaîne de données JSON, comment puis-je transformer cette chaîne en un objet JavaScript en toute sécurité?

Évidemment, je peux le faire en toute sécurité avec quelque chose comme:

var obj = eval("(" + json + ')');

mais cela me rend vulnérable à la chaîne JSON contenant un autre code, qu'il semble très dangereux d'évaluer simplement.


77
Dans la plupart des langues, eval comporte un risque supplémentaire. Eval laisse une porte ouverte pour être exploitée par des pirates. TOUTEFOIS, n'oubliez pas que tout le javascript fonctionne sur le client. ATTENDRE qu'il sera modifié par des pirates. Ils peuvent ÉVALUER tout ce qu'ils veulent, simplement en utilisant la console. Vous devez créer votre protection côté serveur.
Beachhouse

19
Ok, maintenant c'est 2014 et vous ne devriez jamais l'utiliser evalpour analyser une chaîne JSON car vous exposeriez votre code à une "injection de code". Utilisez JSON.parse(yourString)plutôt.
Daniel

Les données JSON sont-elles un littéral?
shanechiu

@shanechiu: si vous voulez dire un type de données scalaire, oui c'est le cas. Est juste une chaîne contenant une syntaxe clé-valeur.
0zkr PM

Réponses:


1963

JSON.parse(jsonString) est une approche JavaScript pure tant que vous pouvez garantir un navigateur raisonnablement moderne.


74
Je suis presque sûr que c'est sûr pour Node.js
Stephen

76
@vsync vous vous rendez compte qu'il s'agit de la SEULE réponse Javascript pur ... si vous lisez la description de la balise javascript, vous verrez ceci ... " À moins qu'une balise pour un framework / bibliothèque ne soit également incluse, une réponse JavaScript pure est attendu. ".. Je lui donne un +1 pour être la seule réponse javascript ...
iConnor


12
Si vous faites NodeJS, il n'y a aucun moyen de charger jQuery juste pour analyser un jsonString dans un objet JSON. Alors votez pour la réponse de Jonathan
Antony

6
Selon ce lien, il est pris en charge par IE8 +, bien qu'il indique:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid

878

La méthode jQuery est désormais obsolète. Utilisez plutôt cette méthode:

let jsonObject = JSON.parse(jsonString);

Réponse originale utilisant la fonctionnalité jQuery obsolète :

Si vous utilisez jQuery, utilisez simplement:

jQuery.parseJSON( jsonString );

C'est exactement ce que vous recherchez (voir la documentation jQuery ).


7
Y a-t-il une raison de l'utiliser sur JSON.parse ()?
Jon

8
jQuery.parseJSONutilise par défaut JSON.parsesi elle existe, donc la seule raison de l'utiliser sur la vraie est si vous avez besoin d'une solution de rechange pour <IE7. Il a été changé depuis jQuery 1.6: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren

9
Mise à jour 2016: à partir de jQuery 3.0, $ .parseJSON est obsolète et vous devez utiliser la méthode native JSON.parse à la place.
jkdev

159

Cette réponse est pour IE <7, pour les navigateurs modernes, vérifiez la réponse de Jonathan ci-dessus.

Cette réponse est obsolète et la réponse de Jonathan ci-dessus ( JSON.parse(jsonString)) est maintenant la meilleure réponse .

JSON.org possède des analyseurs JSON pour de nombreuses langues, dont quatre différentes pour JavaScript. Je pense que la plupart des gens considéreraient json2.js comme leur implémentation goto.


24
Je souhaite que les gens cessent de voter contre cette réponse. Il était exact lorsqu'il a été publié en 2008. Il suffit de voter pour le nouveau.
John

22
Si la réponse est désormais obsolète, pensez à la mettre à jour.
Sotirios Delimanolis

2
pour IE <8, vous devez l'utiliser.
Mahmoodvcs

74

Utilisez l'exemple de code simple dans " JSON.parse () ":

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

et l'inverser:

var str = JSON.stringify(arr);

23

Je ne suis pas sûr des autres façons de le faire, mais voici comment vous le faites dans Prototype (tutoriel JSON) .

new Ajax.Request('/some_url', {
  method:'get',
  requestHeaders: {Accept: 'application/json'},
  onSuccess: function(transport){
    var json = transport.responseText.evalJSON(true);
  }
});

L'appel evalJSON()avec true comme argument purifie la chaîne entrante.


22

Cela semble être le problème:

Une entrée reçue via Ajax websocket, etc., et elle sera au format String, mais vous devez savoir si elle l'est JSON.parsable. Le problème est que, si vous l'exécutez toujours JSON.parse, le programme PEUT continuer "avec succès" mais vous verrez toujours une erreur lancée dans la console avec le redouté "Error: unexpected token 'x'".

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});

NON. Le problème est que vous attendez un objet JSON et que vous pourriez vous retrouver avec des (function(){ postCookiesToHostileServer(); }());choses encore plus méchantes dans le contexte de Node.
Yaur

Eh bien, JSON.parse frotte l'entrée des fonctions (ce qui dans ce cas n'aiderait pas car c'est un objet IIF ->). Il semble que la meilleure façon d'aborder ce sujet soit try / catch. (Voir edit)
Cody

18

Si vous utilisez jQuery , vous pouvez également utiliser:

$.getJSON(url, function(data) { });

Ensuite, vous pouvez faire des choses comme

data.key1.something
data.key1.something_else

etc.


vous utilisez jQuery, n'est-ce pas?
Alexandre C.

15
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

Le rappel est transmis aux données renvoyées, qui seront un objet ou un tableau JavaScript tel que défini par la structure JSON et analysé à l'aide de la $.parseJSON()méthode.


12

Juste pour le plaisir, voici un moyen d'utiliser une fonction:

 jsonObject = (new Function('return ' + jsonFormatData))()

1
Approche intéressante, je ne suis pas sûr de l'utiliser avec JSON.Parse disponible, mais c'est agréable de voir quelqu'un penser en dehors de la boîte.

5
Ceci est très similaire à une simple utilisation evalet n'est pas sûr. : P
Florrie

7
Cela présente tous les inconvénients de l'utilisation, evalmais est plus compliqué et plus difficile à comprendre pour les responsables.
Quentin

9

L'utilisation JSON.parseest probablement la meilleure façon.

Voici un exemple de démonstration en direct .

var jsonRes = '{ "students" : [' +
          '{ "firstName":"Michel" , "lastName":"John" ,"age":18},' +
          '{ "firstName":"Richard" , "lastName":"Joe","age":20 },' +
          '{ "firstName":"James" , "lastName":"Henry","age":15 } ]}';
var studentObject = JSON.parse(jsonRes);

9

La façon la plus simple d'utiliser la parse()méthode:

var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);

Ensuite, vous pouvez obtenir les valeurs des éléments JSON, par exemple:

var myResponseResult = JsonObject.result;
var myResponseCount = JsonObject.count;

Utilisation de jQuery comme décrit dans la jQuery.parseJSON()documentation:

JSON.parse(jsonString);

9

Essayez d'utiliser la méthode avec cet objet Data. ex: Data='{result:true,count:1}'

try {
  eval('var obj=' + Data);
  console.log(obj.count);
}
catch(e) {
  console.log(e.message);
}

Cette méthode aide vraiment dans Nodejs lorsque vous travaillez avec la programmation de port série


C'est vraiment drôle de voir comment les gens sont obsédés par "eval is evil" et ils feront tout pour l'éviter, même en
réécrivant

Le consensus est-il que cette astuce est une méthode sûre pour transformer une chaîne en objet JSON? Je pourrais l'utiliser car aucune importation js supplémentaire n'est nécessaire.
Qui

1
N'IMPORTE QUELLE approche utilisant evalou Functionest tout aussi vulnérable
Slai

undefined; function bye() {...} bye();
Salvioner

5

J'ai trouvé une "meilleure" façon:

Dans CoffeeScript:

try data = JSON.parse(jqxhr.responseText)
data ||= { message: 'Server error, please retry' }

En Javascript:

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});

4

L'analyse JSON est toujours pénible. Si l'entrée n'est pas celle attendue, elle génère une erreur et bloque ce que vous faites.

Vous pouvez utiliser la petite fonction suivante pour analyser en toute sécurité votre entrée. Il transforme toujours un objet même si l'entrée n'est pas valide ou est déjà un objet, ce qui est préférable dans la plupart des cas:

JSON.safeParse = function (input, def) {
  // Convert null to empty object
  if (!input) {
    return def || {};
  } else if (Object.prototype.toString.call(input) === '[object Object]') {
    return input;
  }
  try {
    return JSON.parse(input);
  } catch (e) {
    return def || {};
  }
};

Object.prototype.toString.call(input) === '[object Object]'devrait être l' typeof input === 'object'OMI
Serge K.

typeof input renvoie également l'objet pour null et les tableaux. Ce n'est donc pas le moyen sûr de le faire.
Tahsin Turkoz

Vous avez déjà couvert le nullcas auparavant, et un tableau est un objet. Si vous voulez le tester, vous pouvez l'utiliser instanceof. De plus, si vous donnez une fonction à cette fonction Array, elle va intercepter et return defquand elle aurait pu retourner le tableau parfaitement fin.
Serge K.

Mon commentaire portait sur le bon sens en attrapant des objets. Ma fonction peut avoir plusieurs empêchements mais l'utilisation de typeof input n'est pas le moyen préféré de détecter des objets en général.
Tahsin Turkoz

OMI, le bon sens n'utilise pas de toString()méthode pour vérifier si une variable est un objet ou non. Voir AngularJS , jQuery , Underscore ou même devs
Serge K.


3

Si nous avons une chaîne comme celle-ci:

"{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"

alors nous pouvons simplement utiliser JSON.parsedeux fois pour convertir cette chaîne en un objet JSON:

var sampleString = "{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"
var jsonString= JSON.parse(sampleString)
var jsonObject= JSON.parse(jsonString)

Et nous pouvons extraire des valeurs de l'objet JSON en utilisant:

// instead of last JSON.parse:
var { status, token } = JSON.parse(jsonString);

Le résultat sera:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059

3

JSON.parse() convertit toute chaîne JSON passée dans la fonction en un objet JSON.

Pour mieux le comprendre, appuyez sur F12pour ouvrir «Inspecter l'élément» dans votre navigateur et accédez à la console pour écrire les commandes suivantes:

var response = '{"result":true,"count":1}'; //sample json object(string form)
JSON.parse(response); //converts passed string to JSON Object.

Exécutez maintenant la commande:

console.log(JSON.parse(response));

Vous obtiendrez une sortie en tant qu'objet {result: true, count: 1}.

Pour utiliser cet objet, vous pouvez l'affecter à la variable, peut-être obj:

var obj = JSON.parse(response);

En utilisant objet l' .opérateur point ( ), vous pouvez accéder aux propriétés de l'objet JSON.

Essayez d'exécuter la commande:

console.log(obj.result);

3

Documentation officielle :

La JSON.parse()méthode analyse une chaîne JSON, construisant la valeur ou l'objet JavaScript décrit par la chaîne. Une reviverfonction facultative peut être fournie pour effectuer une transformation sur l'objet résultant avant son retour.

Syntaxe:

JSON.parse(text[, reviver])

Paramètres:

text : La chaîne à analyser en JSON. Voir l'objet JSON pour une description de la syntaxe JSON.

reviver (optional) : S'il s'agit d'une fonction, elle prescrit comment la valeur produite à l'origine par l'analyse est transformée, avant d'être renvoyée.

Valeur de retour

Objet correspondant au texte JSON donné.

Exceptions

Lève une exception SyntaxError si la chaîne à analyser n'est pas JSON valide.



2

Analysez la chaîne JSON avec JSON.parse()et les données deviennent un objet JavaScript:

JSON.parse(jsonString)

Ici, JSON représente pour traiter l'ensemble de données JSON.

Imaginez que nous ayons reçu ce texte d'un serveur Web:

'{ "name":"John", "age":30, "city":"New York"}'

Pour analyser un objet JSON:

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}'); 

Voici objl'objet JSON respectif qui ressemble à:

{ "name":"John", "age":30, "city":"New York"}

Pour récupérer une valeur, utilisez l' .opérateur:

obj.name // John
obj.age //30

Convertissez un objet JavaScript en chaîne avec JSON.stringify().


1

Juste pour analyser la couverture pour différents types d'entrée

Analysez les données avec JSON.parse (), et les données deviennent un objet JavaScript.

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');

Lors de l'utilisation de JSON.parse () sur un JSON dérivé d'un tableau, la méthode renvoie un tableau JavaScript au lieu d'un objet JavaScript.

var myArr = JSON.parse(this.responseText);
console.log(myArr[0]);

Les objets de date ne sont pas autorisés dans JSON. Pour les dates, faites quelque chose comme ça

var text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}';
var obj = JSON.parse(text);
obj.birth = new Date(obj.birth);

Les fonctions ne sont pas autorisées dans JSON. Si vous devez inclure une fonction, écrivez-la sous forme de chaîne.

var text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}';
var obj = JSON.parse(text);
obj.age = eval("(" + obj.age + ")");

0

Question plus ancienne, je sais, mais personne ne remarque cette solution en utilisant new Function(), une fonction anonyme qui renvoie les données.


Juste un exemple:

 var oData = 'test1:"This is my object",test2:"This is my object"';

 if( typeof oData !== 'object' )
  try {
   oData = (new Function('return {'+oData+'};'))();
  }
  catch(e) { oData=false; }

 if( typeof oData !== 'object' )
  { alert( 'Error in code' ); }
 else {
        alert( oData.test1 );
        alert( oData.test2 );
      }

C'est un peu plus sûr car il s'exécute à l'intérieur d'une fonction et ne compile pas directement dans votre code. Donc, s'il y a une déclaration de fonction à l'intérieur, elle ne sera pas liée à l'objet window par défaut.

Je l'utilise pour «compiler» les paramètres de configuration des éléments DOM (par exemple l'attribut de données) de manière simple et rapide.


0

Sommaire:

Javascript (navigateur et NodeJS) ont un JSONobjet intégré . Sur cet objet sont 2 méthodes pratiques pour traiter JSON. Ce sont les suivants:

  1. JSON.parse() Prend JSONcomme argument, retourne un objet JS
  2. JSON.stringify() Prend l'objet JS comme argument renvoie l' JSONobjet

Autres applications:

En outre, pour les traiter très facilement, JSONils peuvent être utilisés à d'autres fins. La combinaison des deux JSONméthodes nous permet de créer très facilement des clones profonds de tableaux ou d'objets. Par exemple:

let arr1 = [1, 2, [3 ,4]];
let newArr = arr1.slice();

arr1[2][0] = 'changed'; 
console.log(newArr); // not a deep clone

let arr2 = [1, 2, [3 ,4]];
let newArrDeepclone = JSON.parse(JSON.stringify(arr2));

arr2[2][0] = 'changed'; 
console.log(newArrDeepclone); // A deep clone, values unchanged


0

Vous pouvez également utiliser la reviverfonction pour filtrer.

var data = JSON.parse(jsonString, function reviver(key, value) {
   //your code here to filter
});

Pour plus d'informations, lisez JSON.parse.


0

JSON.parse est la bonne façon de convertir une chaîne en objet, mais si la chaîne qui est analysée n'est pas un objet ou si la chaîne n'est pas correcte, elle générera une erreur qui provoquera la rupture du reste du code, ce qui signifie idéal pour envelopper la fonction JSON.parse dans try-catch comme

try{
   let obj = JSON.parse(string);
}catch(err){
   console.log(err);
}

-1

Essayez ceci. Celui-ci est écrit en caractères dactylographiés.

         export function safeJsonParse(str: string) {
               try {
                 return JSON.parse(str);
                   } catch (e) {
                 return str;
                 }
           }

Je suis nouveau sur Typescript. Quel avantage cela ajoute- JSON.parse()t-il?
Marc L.

Si une exception s'est produite, cela retournera la chaîne d'entrée elle
Supun Dharmarathne

-1
/**
 * Safely turning a JSON string into an object
 *
 * @param {String} str - JSON String
 * @returns deserialized object, false if error
 */
export function jsonParse(str) {
  let data = null;
  try {
    data = JSON.parse(str);
  } catch (err) {
    return false;
  }
  return data;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.