Converti stringa di oggetti in JSON


165

Come posso convertire una stringa che descrive un oggetto in una stringa JSON usando JavaScript (o jQuery)?

ad es .: Converti questo ( NON una stringa JSON valida):

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"

in questo:

str = '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

Mi piacerebbe evitare di usare eval()se possibile.


Perché la tua stringa non è JSON valida in primo luogo? Come lo stai generando?
Rocket Hazmat,

2
La stringa è memorizzata in un data-attrubute, in questo modo: <div data-object="{hello:'world'}"></div>e non voglio usare virgolette singole in HTML (quindi probabilmente non ci si può fidare)
snorpey

5
@snorpey: <div data-object='{"hello":"world"}'></div>è un HTML valido al 100% (cosa hanno a che fare le virgolette singole con la fiducia o no?). Se lo fai in questo modo, puoi JSON.parsefarlo e funzionerà bene. Nota: anche le chiavi devono essere quotate.
Rocket Hazmat,

@Rocket grazie per i tuoi sforzi! Volevo solo trovare un modo per evitare di usare virgolette singole in HTML (anche se è valido al 100%) e notazione JSON.
snorpey,

@snorpey: si aggirano per non mettere JSON in un attributo HTML in primo luogo. Immagino che potresti usare doppie virgolette e sfuggire a quelle nel JSON <div data-object="{\"hello\":\"world\"}"></div>. Se non desideri utilizzare un JSON valido nell'attributo, dovrai creare il tuo formato e analizzarlo da solo.
Rocket Hazmat,

Risposte:


181

Se la stringa è da una fonte attendibile , è possibile utilizzare evalquindi JSON.stringifyil risultato. Come questo:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

Nota che quando sei evalun oggetto letterale, deve essere racchiuso tra parentesi, altrimenti le parentesi graffe vengono analizzate come un blocco anziché un oggetto.

Concordo anche con i commenti sotto la domanda che sarebbe molto meglio codificare l'oggetto in JSON valido per cominciare ed evitare di dover analizzare, codificare, quindi presumibilmente analizzarlo di nuovo . HTML supporta gli attributi a virgoletta singola (assicurati di codificare in HTML tutte le virgolette singole all'interno delle stringhe).


questo non ha senso, se la stringa proviene da una fonte attendibile, perché la convertiamo invece la rendiamo json valida.
Allenhwkim,

2
@allenhwkim L'idea è di convertire da JSON non valido a JSON valido, quindi evalconverte la stringa in un oggetto JavaScript (che funziona, purché la stringa rappresenti JavaScript valido, anche se non è JSON valido). Quindi JSON.stringifyconverte da un oggetto in una stringa JSON (valida). La chiamata evalè pericolosa se la stringa non proviene da una fonte attendibile perché potrebbe letteralmente eseguire qualsiasi JavaScript che apre la possibilità di attacchi di scripting tra siti.
Matthew Crumley,

2
eval farà comunque cose cattive in questo caso se la stringa è costruita, ad esempio, in questo modo: var str = "(function () {console.log (\" bad \ ")}) ()";
Rondo,

L'uso di eval () eseguirà il codice JS. Può essere facilmente abusato.
FisNaN,

@allenhwkim: non ci fidiamo mai di alcuna fonte. Affidarsi all'IT significa controllare, controllare e ricontrollare.
Laszlo Varga,

110

La tua stringa non è JSON valida, quindi JSON.parse(o jQuery $.parseJSON) non funzionerà.

Un modo potrebbe essere quello evaldi "analizzare" il JSON "non valido", e quindi stringifydi "convertirlo" in JSON valido.

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
str = JSON.stringify(eval('('+str+')'));

Suggerisco invece di provare a "correggere" il tuo JSON non valido, in primo luogo inizi con JSON valido. Come viene strgenerato, dovrebbe essere corretto lì, prima che venga generato, non dopo.

EDIT : Hai detto (nei commenti) che questa stringa è memorizzata in un attributo di dati:

<div data-object="{hello:'world'}"></div>

Ti suggerisco di risolverlo qui, quindi può essere solo JSON.parsed. Innanzitutto, sia le chiavi che i valori devono essere racchiusi tra virgolette doppie. Dovrebbe apparire (gli attributi con virgolette singole in HTML sono validi):

<div data-object='{"hello":"world"}'></div>

Ora puoi semplicemente usare JSON.parse(o jQuery $.parseJSON).

var str = '{"hello":"world"}';
var obj = JSON.parse(str);

49

jQuery.parseJSON

str = jQuery.parseJSON(str)

Modificare. Questo a condizione che tu abbia una stringa JSON valida


1
true Ho visto la domanda su come convertire la stringa JSON in oggetto
Farmor

43

Usa un semplice codice nel link seguente:

http://msdn.microsoft.com/es-es/library/ie/cc836466%28v=vs.94%29.aspx

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

e viceversa

var str = JSON.stringify(arr);

La conversione di jsontext in un oggetto String tramite la nuova stringa (jsontext) è probabilmente ancora migliore, per la sicurezza dei tipi.
Analisi fuzzy

@fuzzyanalysis: No, i wrapper primitivi non devono mai essere utilizzati.
Ry-

1
JSON.parse () dovrebbe essere la risposta accettata qui come affermato da @LouiseMcMahon
pixel 67

24

Spero che questa piccola funzione converta una stringa JSON non valida in una valida.

function JSONize(str) {
  return str
    // wrap keys without quote with valid double quote
    .replace(/([\$\w]+)\s*:/g, function(_, $1){return '"'+$1+'":'})    
    // replacing single quote wrapped ones to double quote 
    .replace(/'([^']+)'/g, function(_, $1){return '"'+$1+'"'})         
}

Risultato

var invalidJSON = "{ hello: 'world',foo:1,  bar  : '2', foo1: 1, _bar : 2, $2: 3, 'xxx': 5, \"fuz\": 4, places: ['Africa', 'America', 'Asia', 'Australia'] }"
JSON.parse(invalidJSON) 
//Result: Uncaught SyntaxError: Unexpected token h VM1058:2
JSON.parse(JSONize(invalidJSON)) 
//Result: Object {hello: "world", foo: 1, bar: "2", foo1: 1, _bar: 2…}

Stiamo provando a de-valutare b usando JSON.parse il nostro codice e questa sembra una buona soluzione. Dovremo ancora gestire la sostituzione costante a mano, ma almeno questo consente di contenere quei casi.
ravemir,

1
È quasi perfetto Non funziona quando si : trova in uno dei valori.
seler

9

Usare con cautela (a causa di eval()):

function strToJson(str) {
  eval("var x = " + str + ";");
  return JSON.stringify(x);
}

chiama come:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
alert( strToJson(str) );

3
Al votante anonimo. Ti sfido a fornire una soluzione migliore. A parte questo, una ragione per il voto negativo sarebbe buona.
Tomalak,

1
@Rocket: ti sbagli. a) eval()è l'unico modo per farlo. b) Ho avvertito l'OP al riguardo. c) Guarda la risposta di Matthew Crumley e pensa a una spiegazione migliore. (Oh, e d) l'affermazione eval()è cattiva è una sciocchezza in questa forma generalizzata.)
Tomalak,

2
@Rocket: Ah, malinteso proprio lì. Mi dispiace, ho pensato che il voto negativo fosse tuo. :)
Tomalak il

1
@kuboslav: funziona benissimo, l'hai anche provato? Sta facendo ciò eval("var x = " + str + ";")che è totalmente valido per JS. Non devi fare var x = ({a:12}).
Rocket Hazmat,

2
@kuboslav Non funziona in IE7 perché IE7 non ha il supporto JSON nativo. Inizierà a funzionare non appena lo usi json2.js. Non essere così felice.
Tomalak,

4

Disclaimer: non provarlo a casa o per qualsiasi cosa che richieda ad altri sviluppatori di prenderti sul serio:

JSON.stringify(eval('(' + str + ')'));

Ecco, l'ho fatto.
Cerca di non farlo, eval è MALE per te. Come detto sopra, utilizzare lo shim JSON di Crockford per i browser più vecchi (IE7 e precedenti)

Questo metodo richiede che la stringa sia javascript valida , che verrà convertita in un oggetto javascript che può quindi essere serializzato in JSON.

modifica: risolto come suggerito da Rocket.


Dovrebbe essere JSON.stringify(eval('('+str+')'));, non che io la perdoni eval, ma la sua stringa non è JSON valida, quindi JSON.parsenon funziona.
Rocket Hazmat,

4

Ho messo la mia risposta per qualcuno che è interessato a questo vecchio thread.

Ho creato il parser HTML5 data- * per il plugin e la demo jQuery che converte una stringa JSON non valida in un oggetto JavaScript senza usare eval().

Può passare i seguenti dati * * attributi HTML5:

<div data-object='{"hello":"world"}'></div>
<div data-object="{hello:'world'}"></div>
<div data-object="hello:world"></div>

nell'oggetto:

{
    hello: "world"
}


2

C'è un modo molto più semplice per realizzare questa impresa, basta dirottare l'attributo onclick di un elemento fittizio per forzare un ritorno della stringa come oggetto JavaScript:

var jsonify = (function(div){
  return function(json){
    div.setAttribute('onclick', 'this.__json__ = ' + json);
    div.click();
    return div.__json__;
  }
})(document.createElement('div'));

// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)

Ecco una demo: http://codepen.io/csuwldcat/pen/dfzsu (apri la tua console)


2

È necessario utilizzare "eval", quindi JSON.stringify e JSON.parse per il risultato.

 var errorString= "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
 var jsonValidString = JSON.stringify(eval("(" + errorString+ ")"));
 var JSONObj=JSON.parse(jsonValidString);

inserisci qui la descrizione dell'immagine


1

Devi scrivere parentesi tonde, perché senza di esse evalconsidereremo il codice tra parentesi graffe come un blocco di comandi.

var i = eval("({ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] })");

1

La tua scommessa migliore e più sicura sarebbe JSON5 - JSON per gli umani . È stato creato appositamente per quel caso d'uso.

const result = JSON5.parse("{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }");

console.log(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/json5/0.5.1/json5.min.js"></script>


1

L'uso di new Function () è meglio di eval, ma dovrebbe comunque essere usato solo con input sicuri.

const parseJSON = obj => Function('"use strict";return (' + obj + ')')();

console.log(parseJSON("{a:(4-1), b:function(){}, c:new Date()}"))
// outputs: Object { a: 3, b: b(), c: Date 2019-06-05T09:55:11.777Z }

Fonti: MDN , 2alità


0

Per il tuo semplice esempio sopra, puoi farlo usando 2 semplici sostituzioni regex:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
str.replace(/(\w+):/g, '"$1":').replace(/'/g, '"');
 => '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

Grande avvertenza : questo approccio ingenuo presuppone che l'oggetto non abbia stringhe contenenti un 'o :carattere. Ad esempio, non riesco a pensare a un buon modo per convertire la seguente stringa di oggetti in JSON senza usare eval:

"{ hello: 'world', places: [\"America: The Progressive's Nightmare\"] }"

0

Solo per le stranezze, puoi convertire la tua stringa tramite babel-standalone

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";

function toJSON() {
  return {
    visitor: {
      Identifier(path) {
        path.node.name = '"' + path.node.name + '"'
      },
      StringLiteral(path) {
        delete path.node.extra
      }
    }
  }
}
Babel.registerPlugin('toJSON', toJSON);
var parsed = Babel.transform('(' + str + ')', {
  plugins: ['toJSON']
});
var json = parsed.code.slice(1, -2)
console.log(JSON.parse(json))
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>


0

var str = "{hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia']}" var fStr = str .replace (/ ([Az] *) (:) / g, '"$ 1":') .replace (/ '/ g, "\" ")

console.log (JSON.parse (FSTR))inserisci qui la descrizione dell'immagine

Scusa, sono sul mio telefono, ecco una foto.


0

Una soluzione con un regex e non usando eval:

str.replace(/([\s\S]*?)(')(.+?)(')([\s\S]*?)/g, "$1\"$3\"$5")

Questo credo che dovrebbe funzionare per più righe e tutte le possibili occorrenze (/ g flag) della 'stringa' a virgoletta singola sostituita da "stringa" a virgoletta doppia.


0
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

-1

Forse devi provare questo:

str = jQuery.parseJSON(str)

Domanda specificata "o jQuery" e questa è la soluzione perfetta se è disponibile.
Ecropolis,
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.