Konvertieren Sie die Objektzeichenfolge in JSON

165

Wie kann ich eine Zeichenfolge, die ein Objekt beschreibt, mithilfe von JavaScript (oder jQuery) in eine JSON-Zeichenfolge konvertieren?

Beispiel: Konvertieren Sie dies ( KEINE gültige JSON-Zeichenfolge):

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

das mögen:

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

Ich würde es gerne vermeiden, eval()wenn möglich.

Snorpey
quelle
Warum ist Ihre Zeichenfolge überhaupt nicht gültig? Wie generierst du das?
Rocket Hazmat
2
Die Zeichenfolge wird in einem data-attrubute wie folgt gespeichert : <div data-object="{hello:'world'}"></div>und ich möchte keine einfachen Anführungszeichen im HTML verwenden (daher ist es wahrscheinlich nicht vertrauenswürdig)
snorpey
5
@snorpey: <div data-object='{"hello":"world"}'></div>ist 100% gültiges HTML (was haben einfache Anführungszeichen damit zu tun, ihm zu vertrauen oder nicht?). Wenn Sie es so machen, können Sie es einfach JSON.parseund es wird gut funktionieren. Hinweis: Die Schlüssel müssen ebenfalls in Anführungszeichen gesetzt werden.
Rocket Hazmat
@Rocket danke für deine Bemühungen! Ich wollte nur einen Weg finden, um einfache Anführungszeichen in HTML (obwohl es zu 100% gültig ist) und JSON-Notation verwenden zu müssen.
Snorpey
@snorpey: Sie umgehen JSON nicht in erster Linie in ein HTML-Attribut. Ich denke, Sie könnten doppelte Anführungszeichen verwenden und denen im JSON entkommen <div data-object="{\"hello\":\"world\"}"></div>. Wenn Sie kein gültiges JSON im Attribut verwenden möchten, müssen Sie Ihr eigenes Format erstellen und es selbst analysieren.
Rocket Hazmat

Antworten:

181

Wenn die Zeichenfolge aus einer vertrauenswürdigen Quelle stammen , könnten Sie evaldann JSON.stringifydas Ergebnis. So was:

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

Beachten Sie, dass, wenn Sie eval ein Objektliteral in Klammern eingeschlossen werden muss, andernfalls werden die geschweiften Klammern als Block anstelle eines Objekts analysiert.

Ich stimme auch mit den Kommentaren unter der Frage , dass es viel besser ist das Objekt in gültiger JSON nur kodieren wäre zu beginnen und zu vermeiden, kodieren zu analysieren ist, dann vermutlich analysiert es wieder . HTML unterstützt Attribute in einfachen Anführungszeichen (stellen Sie nur sicher, dass alle einfachen Anführungszeichen in Zeichenfolgen HTML-codiert sind).

Matthew Crumley
quelle
Dies ist nicht sinnvoll, wenn die Zeichenfolge aus einer vertrauenswürdigen Quelle stammt. Warum konvertieren wir sie stattdessen als gültigen JSON?
Allenhwkim
2
@allenhwkim Die Idee ist, von ungültigem JSON in gültiges JSON zu konvertieren, also evaldie Zeichenfolge in ein JavaScript-Objekt zu konvertieren (was funktioniert, solange die Zeichenfolge gültiges JavaScript darstellt, auch wenn es kein gültiges JSON ist). Dann JSON.stringifywandelt die von einem Objekt zurück zu einem (gültig) JSON String. Das Aufrufen evalist gefährlich, wenn die Zeichenfolge nicht aus einer vertrauenswürdigen Quelle stammt, da buchstäblich jedes JavaScript ausgeführt werden kann, das die Möglichkeit von Cross-Site-Scripting-Angriffen eröffnet.
Matthew Crumley
2
eval wird in diesem Fall immer noch schlechte Dinge tun, wenn die Zeichenfolge beispielsweise so aufgebaut ist: var str = "(function () {console.log (" bad ")}) ()";
Rondo
Mit eval () wird JS-Code ausgeführt. Es kann leicht missbraucht werden.
FisNaN
@allenhwkim: Wir vertrauen niemals einer Quelle. Vertrauen in die IT bedeutet prüfen, prüfen und erneut prüfen.
Laszlo Varga
110

Ihre Zeichenfolge ist nicht gültig JSON, also JSON.parse(oder jQuery's$.parseJSON funktioniert ) nicht.

Eine Möglichkeit wäre, evalden "ungültigen" JSON zu "analysieren" und ihn dann stringifyin einen gültigen JSON zu "konvertieren".

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

Ich schlage vor, anstatt zu versuchen, Ihren ungültigen JSON zu "reparieren", beginnen Sie zunächst mit einem gültigen JSON. Wie strgeneriert wird, sollte dort festgelegt werden, bevor es generiert wird, nicht danach.

EDIT : Sie sagten (in den Kommentaren), dass diese Zeichenfolge in einem Datenattribut gespeichert ist:

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

Ich schlage vor, Sie beheben es hier, so dass es einfach JSON.parsed sein kann. Zunächst müssen sowohl die Schlüssel als auch die Werte in doppelte Anführungszeichen gesetzt werden. Es sollte so aussehen (Attribute in einfachen Anführungszeichen in HTML sind gültig):

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

Jetzt können Sie einfach JSON.parse(oder jQuery's $.parseJSON) verwenden.

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

jQuery.parseJSON

str = jQuery.parseJSON(str)

Bearbeiten. Vorausgesetzt, Sie haben eine gültige JSON-Zeichenfolge

Bauer
quelle
1
true Ich sah die Frage, wie man JSON-String in Objekt konvertiert
Farmor
43

Verwenden Sie einfachen Code im folgenden Link:

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

und umgekehrt

var str = JSON.stringify(arr);
Ronald
quelle
Das Konvertieren von jsontext in ein String-Objekt über einen neuen String (jsontext) ist aus Gründen der Typensicherheit wahrscheinlich sogar noch besser.
Fuzzy-Analyse
@fuzzyanalysis: Nein, primitive Wrapper sollten niemals verwendet werden.
Ry-
1
JSON.parse () sollte hier die akzeptierte Antwort sein, wie von @LouiseMcMahon angegeben
Pixel 67
24

Ich hoffe, diese kleine Funktion konvertiert ungültige JSON-Zeichenfolgen in gültige.

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+'"'})         
}

Ergebnis

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…}
allenhwkim
quelle
Wir versuchen, b mithilfe von JSON zu entwerten. Analysieren Sie unseren Code, und dies scheint eine gute Lösung zu sein. Wir werden immer noch den ständigen Austausch von Hand erledigen müssen, aber dies ermöglicht es zumindest, diese Fälle einzudämmen.
Ravemir
1
Es ist fast perfekt. Funktioniert nicht, wenn : sich einer der Werte befindet.
Seler
9

Vorsichtig anwenden (wegen eval()):

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

Anruf als:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
alert( strToJson(str) );
Tomalak
quelle
3
An den anonymen Downwähler. Ich fordere Sie auf, eine bessere Lösung anzubieten. Abgesehen davon wäre ein Grund für die Ablehnung schön.
Tomalak
1
@ Rocket: Du liegst falsch. a) eval()ist der einzige Weg, dies zu tun. b) Ich habe das OP darauf hingewiesen. c) Sehen Sie sich Matthew Crumleys Antwort an und überlegen Sie sich eine bessere Erklärung. (Oh, und d) die Aussage eval()ist schlecht ist Unsinn in dieser verallgemeinerten Form.)
Tomalak
2
@ Rocket: Ah, genau dort Missverständnisse. Entschuldigung, ich dachte, die Abwertung liegt bei Ihnen. :)
Tomalak
1
@ Kuboslav: Es funktioniert gut, hast du es überhaupt getestet? Er tut, eval("var x = " + str + ";")was absolut gültig ist JS. Das musst du nicht tun var x = ({a:12}).
Rocket Hazmat
2
@kuboslav Es funktioniert nicht in IE7, da IE7 keine native JSON-Unterstützung bietet. Sobald Sie es verwenden, beginnt es zu funktionieren json2.js. Sei nicht so triggerglücklich.
Tomalak
4

Haftungsausschluss: Versuchen Sie dies nicht zu Hause oder für Dinge, bei denen andere Entwickler Sie ernst nehmen müssen:

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

Dort habe ich es getan.
Versuche es nicht zu tun, eval ist SCHLECHT für dich. Verwenden Sie wie oben beschrieben Crockfords JSON-Shim für ältere Browser (IE7 und darunter).

Für diese Methode muss Ihre Zeichenfolge ein gültiges Javascript sein , das in ein Javascript-Objekt konvertiert wird, das dann in JSON serialisiert werden kann.

edit: behoben wie von Rocket vorgeschlagen.

Gonchuki
quelle
Es sollte sein JSON.stringify(eval('('+str+')'));, dass ich es nicht gutheiße eval, aber seine Zeichenfolge ist kein gültiger JSON, JSON.parsefunktioniert also nicht.
Rocket Hazmat
4

Ich habe meine Antwort für jemanden gegeben, der sich für diesen alten Thread interessiert.

Ich habe den HTML5-Daten- * Parser für das jQuery-Plugin und die Demo erstellt , die eine fehlerhafte JSON-Zeichenfolge ohne Verwendung in ein JavaScript-Objekt konvertieren eval().

Es kann die folgenden HTML5-Daten- * Attribute übergeben:

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

in das Objekt:

{
    hello: "world"
}
tokkonopapa
quelle
2

Douglas Crockford hat einen Konverter, aber ich bin nicht sicher, ob er bei schlechtem JSON zu gutem JSON helfen wird.

https://github.com/douglascrockford/JSON-js

Seth
quelle
Dies hilft nicht wirklich, da die Zeichenfolge kein gültiger JSON ist.
Rocket Hazmat
2

Es gibt eine viel einfachere Möglichkeit, dieses Kunststück zu erreichen. Entführen Sie einfach das onclick-Attribut eines Dummy-Elements, um die Rückgabe Ihrer Zeichenfolge als JavaScript-Objekt zu erzwingen:

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

Hier ist eine Demo: http://codepen.io/csuwldcat/pen/dfzsu (öffnen Sie Ihre Konsole)

csuwldcat
quelle
2

Sie müssen "eval", dann JSON.stringify und dann JSON.parse für das Ergebnis verwenden.

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

Geben Sie hier die Bildbeschreibung ein

Negi Rox
quelle
1

Sie müssen runde Klammern schreiben, da ohne sie evalCode in geschweiften Klammern als Befehlsblock betrachtet wird.

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

Ihre beste und sicherste Wette wäre JSON5 - JSON für Menschen . Es wurde speziell für diesen Anwendungsfall erstellt.

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>

dereli
quelle
1

Die Verwendung von new Function () ist besser als eval, sollte jedoch nur mit sicherer Eingabe verwendet werden.

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 }

Quellen: MDN , 2ality

SamGoody
quelle
0

Für Ihr einfaches Beispiel oben können Sie dies mit 2 einfachen Regex-Ersetzungen tun:

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

Große Einschränkung : Bei diesem naiven Ansatz wird davon ausgegangen , dass das Objekt keine Zeichenfolgen enthält, die ein 'oder ein :Zeichen enthalten. Ich kann mir zum Beispiel keine gute Möglichkeit vorstellen, die folgende Objektzeichenfolge ohne Verwendung in JSON zu konvertieren eval:

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

Nur für die Macken davon können Sie Ihre Zeichenfolge über konvertieren 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>

Moritz Roessler
quelle
0

var str = "{Hallo: 'Welt', Orte: ['Afrika', 'Amerika', 'Asien', 'Australien']}" var fStr = str .replace (/ ([Az] *) (:) / g, '$ 1 ":') .replace (/ '/ g," ")

console.log (JSON.parse (fStr))Geben Sie hier die Bildbeschreibung ein

Entschuldigung, ich bin auf meinem Handy, hier ist ein Bild.

Francis Leigh
quelle
0

Eine Lösung mit einem regulären Ausdruck und ohne Verwendung von eval:

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

Dies sollte meiner Meinung nach für mehrere Zeilen funktionieren und alle möglichen Vorkommen (/ g Flag) von "Zeichenfolge" in einfachen Anführungszeichen werden durch "Zeichenfolge" in doppelten Anführungszeichen ersetzt.

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

Vielleicht müssen Sie dies versuchen:

str = jQuery.parseJSON(str)
grüß dich
quelle
Frage angegeben "oder jQuery" und dies ist die perfekte Lösung, wenn Sie es zur Verfügung haben.
Ecropolis