Comment puis-je convertir une chaîne qui décrit un objet en une chaîne JSON en utilisant JavaScript (ou jQuery)?
par exemple: Convertissez cette (PASune chaîne JSON valide):
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
dans ceci:
str = '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'
J'aimerais éviter d'utiliser eval()
si possible.
Si la chaîne provient d'une source fiable , vous pouvez utiliser eval
puis JSON.stringify
le résultat. Comme ça:
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));
Notez que lorsque vous eval
un littéral d'objet, il doit être entouré de parenthèses, sinon les accolades sont analysées comme un bloc au lieu d'un objet.
Je suis également d'accord avec les commentaires sous la question qu'il serait beaucoup mieux de commencer par encoder l'objet en JSON valide et d'éviter de devoir analyser, encoder, puis vraisemblablement l'analyser again. HTML prend en charge les attributs entre guillemets (veillez simplement à coder HTML les guillemets simples dans les chaînes).
Votre chaîne n'est pas un code JSON valide. Par conséquent, JSON.parse
(ou $.parseJSON
de jQuery) ne fonctionnera pas.
Une solution serait d'utiliser eval
pour "analyser" le JSON "non valide", puis stringify
pour le "convertir" en JSON valide.
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
str = JSON.stringify(eval('('+str+')'));
Je suggère au lieu d'essayer de "réparer" votre JSON invalide, vous commencez par un JSON valide. Comment str
est généré, il devrait être corrigé ici, avant sa génération, pas après.
EDIT: Vous avez dit (dans les commentaires) que cette chaîne est stockée dans un attribut de données:
<div data-object="{hello:'world'}"></div>
Je suggère que vous le répariez ici, donc ça peut simplement être JSON.parse
d. Premièrement, les clés et les valeurs doivent être entre guillemets doubles. Cela devrait ressembler à (les attributs entre guillemets HTML sont valides):
<div data-object='{"hello":"world"}'></div>
Maintenant, vous pouvez simplement utiliser JSON.parse
(ou le $.parseJSON
de jQuery).
var str = '{"hello":"world"}';
var obj = JSON.parse(str);
str = jQuery.parseJSON(str)
Modifier. Ceci est fourni si vous avez une chaîne JSON valide
Utilisez un code simple dans le lien ci-dessous:
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);
et inverser
var str = JSON.stringify(arr);
J'espère que cette petite fonction convertit une chaîne JSON non valide en une chaîne valide.
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+'"'})
}
Résultat
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…}
À utiliser avec prudence (à cause de eval()
):
function strToJson(str) {
eval("var x = " + str + ";");
return JSON.stringify(x);
}
appeler comme:
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
alert( strToJson(str) );
Je mets ma réponse pour quelqu'un qui s'intéresse à ce vieux fil.
J'ai créé l'analyseur HTML5 data- * for jQuery plugin et demo qui convertit une chaîne JSON mal formée en un objet JavaScript sans utiliser eval()
.
Il peut passer les attributs HTML5 data- * ci-dessous:
<div data-object='{"hello":"world"}'></div>
<div data-object="{hello:'world'}"></div>
<div data-object="hello:world"></div>
dans l'objet:
{
hello: "world"
}
Avertissement: n'essayez pas cela à la maison ou pour tout ce qui nécessite que d'autres développeurs vous prennent au sérieux:
JSON.stringify(eval('(' + str + ')'));
Là je l'ai fait.
Essayez de ne pas le faire, eval est MAUVAIS pour vous. Comme indiqué ci-dessus, utilisez la cale JSON de Crockford pour les anciens navigateurs (IE7 et moins).
Cette méthode nécessite que votre chaîne soit valide javascript , qui sera converti en un objet javascript qui peut ensuite être sérialisé en JSON.
edit: corrigé comme suggéré par Rocket.
Douglas Crockford a un convertisseur, mais je ne suis pas sûr que cela aidera avec un mauvais JSON à bon.
Votre meilleur et plus sûr pari serait JSON5 - JSON pour les humains . Il est créé spécifiquement pour ce cas d'utilisation.
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>
Vous devez écrire des crochets, car sans eux eval
considérera le code entre accolades comme un bloc de commandes ..__
var i = eval("({ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] })");
Il existe un moyen beaucoup plus simple d'accomplir cet exploit: il suffit de détourner l'attribut onclick d'un élément factice pour forcer le retour de votre chaîne en tant qu'objet 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 ;)
Voici une démo:http://codepen.io/csuwldcat/pen/dfzsu (ouvrez votre console)
Peut-être que vous devez essayer ceci:
str = jQuery.parseJSON(str)
Juste pour les bizarreries, vous pouvez convertir votre chaîne via 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>
Pour votre exemple simple ci-dessus, vous pouvez le faire en utilisant 2 simples regex simples:
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
str.replace(/(\w+):/g, '"$1":').replace(/'/g, '"');
=> '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'
Big caveat : Cette approche naïve suppose que l'objet ne comporte aucune chaîne contenant un caractère '
ou :
. Par exemple, je ne peux pas trouver un bon moyen de convertir la chaîne d'objet suivante en JSON sans utiliser eval
:
"{ hello: 'world', places: [\"America: The Progressive's Nightmare\"] }"
var str = "{bonjour: 'monde', lieux: ['Afrique', 'Amérique', 'Asie', 'Australie']}" var fStr = str . remplacer (/ ([Az] *) (:)/g, '"$ 1":') . remplacer (/ '/ g, "\" ")
console.log (JSON.parse (fStr))
Désolé je suis sur mon téléphone, voici une photo.
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));
Une solution avec un regex et n'utilisant pas eval:
str.replace(/([\s\S]*?)(')(.+?)(')([\s\S]*?)/g, "$1\"$3\"$5")
Je pense que cela devrait fonctionner pour plusieurs lignes et toutes les occurrences possibles (indicateur/g) de "chaîne" entre guillemets remplacés par "chaîne" entre guillemets doubles.
Utiliser une nouvelle fonction () est préférable à eval, mais ne devrait toujours être utilisé qu'avec une entrée sécurisée.
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 }