Trasformazione sicura di una stringa JSON in un oggetto


1336

Data una stringa di dati JSON, come posso trasformare quella stringa in modo sicuro in un oggetto JavaScript?

Ovviamente posso farlo in modo non sicuro con qualcosa del tipo:

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

ma questo mi rende vulnerabile alla stringa JSON contenente altro codice, che sembra molto pericoloso semplicemente valutare.


77
Nella maggior parte delle lingue, eval comporta un rischio aggiuntivo. Eval lascia una porta aperta per essere sfruttato dagli hacker. TUTTAVIA, ricorda che tutto javascript viene eseguito sul client. ASPETTO che verrà modificato dagli hacker. Possono EVAL tutto quello che vogliono, semplicemente usando la console. È necessario creare la protezione sul lato server.
Beachhouse

19
Ok, ora è il 2014 e non dovresti mai usarlo evalper analizzare una stringa JSON perché esponeresti il ​​tuo codice a "code injection". Usa JSON.parse(yourString)invece.
Daniel,

I dati JSON sono letterali?
shanechiu,

@shanechiu: se intendi un tipo di dati scalare, sì. È solo una stringa con una sintassi valore-chiave al suo interno.
0zkr PM,

Risposte:


1963

JSON.parse(jsonString) è un puro approccio JavaScript purché sia ​​possibile garantire un browser ragionevolmente moderno.


74
Sono abbastanza sicuro che sia sicuro per Node.js
Stephen,

76
@vsync ti rendi conto che questa è l' UNICA pura risposta Javascript ... se leggi la descrizione per il tag javascript vedrai questo ... " A meno che non sia incluso anche un tag per un framework / libreria, una pura risposta JavaScript è previsto. ".. Gli do un +1 per essere l'unica risposta javascript ...
iConnor


12
Se stai facendo NodeJS, non avrei modo di caricare jQuery solo per analizzare un jsonString in un oggetto JSON. Quindi vota la risposta di Jonathan
Antony,

6
Secondo questo link è supportato da IE8 +, anche se dice:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid,

878

Il metodo jQuery è ora obsoleto. Utilizzare invece questo metodo:

let jsonObject = JSON.parse(jsonString);

Risposta originale utilizzando la funzionalità jQuery obsoleta :

Se stai usando jQuery basta usare:

jQuery.parseJSON( jsonString );

È esattamente quello che stai cercando (vedi la documentazione di jQuery ).


7
C'è un motivo per usarlo su JSON.parse ()?
Jon

8
jQuery.parseJSONL'impostazione predefinita è JSON.parsese esiste, quindi l'unico motivo per utilizzarlo su quello reale è se è necessario un fallback per <IE7. È stato cambiato molto tempo fa in jQuery 1.6: james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-Johan Sjögren

9
Aggiornamento 2016: a partire da jQuery 3.0, $ .parseJSON è obsoleto e al suo posto è necessario utilizzare il metodo JSON.parse nativo.
jkdev,

159

Questa risposta è per IE <7, per i browser moderni controlla la risposta di Jonathan sopra.

Questa risposta è obsoleta e la risposta di Jonathan sopra ( JSON.parse(jsonString)) è ora la risposta migliore .

JSON.org ha parser JSON per molte lingue, tra cui quattro diverse per JavaScript. Credo che la maggior parte delle persone considererebbe json2.js la loro implementazione goto.


24
Vorrei che la gente smettesse di votare in negativo questa risposta. Era preciso quando è stato pubblicato nel 2008. Ho appena votato quello nuovo.
John,

22
Se la risposta non è aggiornata, considera di aggiornarla.
Sotirios Delimanolis,

2
per IE <8 è necessario utilizzare questo.
Mahmoodvcs,

74

Utilizzare l'esempio di codice semplice in " JSON.parse () ":

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

e invertendolo:

var str = JSON.stringify(arr);

23

Non sono sicuro di altri modi per farlo, ma ecco come lo fai in Prototype (tutorial JSON) .

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

La chiamata evalJSON()con vero come argomento disattiva la stringa in arrivo.


22

Questo sembra essere il problema:

Un input che viene ricevuto tramite websocket Ajax ecc. E sarà in formato String, ma è necessario sapere se lo è JSON.parsable. Il problema è che, se lo esegui sempre JSON.parse, il programma PU continue continuare "con successo" ma vedrai ancora un errore generato nella console con il temuto "Error: unexpected token 'x'".

var data;

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

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

NO. Il problema è che ti aspetti un oggetto JSON e potresti finire con (function(){ postCookiesToHostileServer(); }());cose ancora più cattive nel contesto di Node.
Yaur,

Bene JSON.parse cancella l'input delle funzioni (che in questo caso non sarebbe d'aiuto in quanto oggetto IIF ->). Sembra che il modo migliore per affrontare questo argomento sia provare / catturare. (Vedi modifica)
Cody

18

Se stai usando jQuery , puoi anche usare:

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

Quindi puoi fare cose come

data.key1.something
data.key1.something_else

eccetera.


stai usando jQuery, vero?
Alexandre C.,

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

Al callback vengono passati i dati restituiti, che saranno un oggetto JavaScript o un array come definito dalla struttura JSON e analizzati utilizzando il $.parseJSON()metodo.


12

Solo per divertimento, ecco un modo per usare una funzione:

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

1
Approccio interessante, non sono sicuro che lo userei con JSON.Parse disponibile, ma è bello vedere qualcuno che pensa fuori dagli schemi.

5
Questo è molto simile al solo utilizzo evalper farlo e non è sicuro. : P
Florrie,

7
Ciò ha tutti gli svantaggi dell'utilizzo, evalma è più complicato e più difficile da comprendere per i manutentori.
Quentin,

9

L'uso JSON.parseè probabilmente il modo migliore.

Ecco un esempio demo live .

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

Il modo più semplice usando il parse()metodo:

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

Quindi è possibile ottenere i valori degli elementi JSON, ad esempio:

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

Utilizzando jQuery come descritto nella jQuery.parseJSON()documentazione:

JSON.parse(jsonString);

9

Prova a utilizzare il metodo con questo oggetto Data. ex: Data='{result:true,count:1}'

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

Questo metodo aiuta davvero in Nodejs quando si lavora con la programmazione della porta seriale


È davvero divertente come le persone siano fissate su "eval is evil" e faranno di tutto per evitarlo, anche riscrivendo l'intera funzionalità di eval ..
Diynevala,

È consenso questo trucco è un metodo sicuro che trasforma la stringa in oggetto JSON? Potrei usarlo perché non sono necessarie ulteriori importazioni js.
Dal

1
QUALSIASI approccio utilizza evalo Functionè ugualmente vulnerabile
Slai

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

5

Ho trovato un modo "migliore":

In CoffeeScript:

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

In Javascript:

var data;

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

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

4

L'analisi JSON è sempre un dolore. Se l'input non è come previsto, genera un errore e blocca ciò che si sta facendo.

Puoi utilizzare la seguente minuscola funzione per analizzare in modo sicuro i tuoi input. Trasforma sempre un oggetto anche se l'input non è valido o è già un oggetto che è migliore nella maggior parte dei casi:

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]'dovrebbe essere l' typeof input === 'object'IMO
Serge K. il

typeof input restituisce oggetto anche per null e array. Quindi non è il modo sicuro per farlo.
Tahsin Turkoz,

Hai già trattato il nullcaso in precedenza e un array è un oggetto. Se vuoi provarlo, puoi usarlo instanceof. Inoltre, se si dà a questa funzione Array, verrà catturata e return defquando avrebbe potuto restituire l'array perfettamente perfetto.
Serge K.

Il mio commento riguardava il buon senso mentre si catturavano oggetti. La mia funzione può avere diversi impedimenti, ma l'uso dell'input typeof non è il modo preferito di rilevare oggetti in generale.
Tahsin Turkoz,

IMO, il buon senso non usa il toString()metodo per verificare se una variabile è un oggetto o no. Vedere AngularJS , jQuery , sottolineatura , o anche Devs
Serge K.


3

Se abbiamo una stringa come questa:

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

allora possiamo semplicemente usare JSON.parsedue volte per convertire questa stringa in un oggetto JSON:

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

E possiamo estrarre valori dall'oggetto JSON usando:

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

Il risultato sarà:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059

3

JSON.parse() converte qualsiasi stringa JSON passata nella funzione in un oggetto JSON.

Per capirlo meglio, premi F12per aprire "Ispeziona elemento" nel tuo browser e vai alla console per scrivere i seguenti comandi:

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

Ora esegui il comando:

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

Otterrai l'output come oggetto {result: true, count: 1}.

Per usare quell'oggetto, puoi assegnarlo alla variabile, forse obj:

var obj = JSON.parse(response);

Utilizzando obje l' .operatore punto ( ) è possibile accedere alle proprietà dell'oggetto JSON.

Prova a eseguire il comando:

console.log(obj.result);

3

Documentazione ufficiale :

Il JSON.parse()metodo analizza una stringa JSON, costruendo il valore JavaScript o l'oggetto descritto dalla stringa. È reviverpossibile fornire una funzione opzionale per eseguire una trasformazione sull'oggetto risultante prima che venga restituito.

Sintassi:

JSON.parse(text[, reviver])

parametri:

text : La stringa da analizzare come JSON. Vedere l'oggetto JSON per una descrizione della sintassi JSON.

reviver (optional) : Se una funzione, questo prescrive come viene trasformato il valore originariamente prodotto dall'analisi prima di essere restituito.

Valore di ritorno

L'oggetto corrispondente al testo JSON dato.

eccezioni

Genera un'eccezione SyntaxError se la stringa da analizzare non è JSON valida.



2

Analizzare la stringa JSON con JSON.parse()e i dati diventano un oggetto JavaScript:

JSON.parse(jsonString)

Qui, JSON rappresenta l'elaborazione del set di dati JSON.

Immagina di aver ricevuto questo testo da un web server:

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

Per analizzare un oggetto JSON:

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

Ecco objil rispettivo oggetto JSON che assomiglia a:

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

Per recuperare un valore utilizzare l' .operatore:

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

Converti un oggetto JavaScript in una stringa con JSON.stringify().


1

Solo per l'analisi della copertina per diversi tipi di input

Analizzare i dati con JSON.parse () e i dati diventano un oggetto JavaScript.

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

Quando si utilizza JSON.parse () su un JSON derivato da un array, il metodo restituirà un array JavaScript anziché un oggetto JavaScript.

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

Gli oggetti data non sono consentiti in JSON. Per le date fai qualcosa del genere

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

Le funzioni non sono consentite in JSON. Se devi includere una funzione, scrivila come stringa.

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

0

Domanda precedente, lo so, tuttavia nessuno nota questa soluzione utilizzando new Function(), una funzione anonima che restituisce i dati.


Solo un esempio:

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

Questo è un po 'più sicuro perché viene eseguito all'interno di una funzione e non viene compilato direttamente nel codice. Quindi, se contiene una dichiarazione di funzione, non sarà associata all'oggetto finestra predefinito.

Lo uso per "compilare" le impostazioni di configurazione degli elementi DOM (ad esempio l'attributo di dati) semplici e veloci.


0

Sommario:

Javascript (sia browser che NodeJS) hanno un JSONoggetto incorporato . Su questo oggetto ci sono 2 metodi convenienti per affrontare JSON. Sono i seguenti:

  1. JSON.parse() Prende JSONcome argomento, restituisce l'oggetto JS
  2. JSON.stringify() Prende l'oggetto JS come argomento restituisce l' JSONoggetto

Altre applicazioni:

Inoltre, per gestire in modo molto conveniente JSON, possono essere utilizzati per altri mezzi. La combinazione di entrambi i JSONmetodi ci consente di rendere molto facili la creazione di cloni profondi di matrici o oggetti. Per esempio:

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

Puoi anche usare la reviverfunzione per filtrare.

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

Per maggiori informazioni leggi JSON.parse.


0

JSON.parse è il modo giusto per convertire una stringa in un oggetto ma se la stringa analizzata non è un oggetto o se la stringa non è corretta, verrà generato un errore che causerà l'interruzione del resto del codice, quindi è ideale per avvolgere la funzione JSON.parse all'interno di try-catch come

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

-1

Prova questo. Questo è scritto in dattiloscritto.

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

Sono nuovo di Typescript. A quale vantaggio aggiunge questo JSON.parse()?
Marc L.

Se si è verificata un'eccezione, ciò restituirà la stringa di input stessa
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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.