Wie kann ich eine JSON-Zeichenfolge mit Zeilenumbrüchen mithilfe von JavaScript umgehen?

166

Ich muss eine JSON-Zeichenfolge bilden, in der ein Wert ein neues Zeilenzeichen hat. Dies muss maskiert und dann mit einem AJAX-Aufruf gebucht werden. Kann jemand einen Weg vorschlagen, um die Zeichenfolge mit JavaScript zu entkommen. Ich verwende jQuery nicht.

Srikant
quelle
1
Ich habe versucht, das neue Zeilenzeichen \ n nach \\ n zu maskieren. Es funktioniert gut. Aber ich suche nach einer JS-Bibliothek, die dies für alle Escape-Zeichen tun kann.
Srikant
1
Warum müssen Sie den Zeilenumbrüchen innerhalb des JSON entkommen? Wie werden diese Werte bei ihrer Verwendung dekodiert, da die geeignete Lösung darin besteht, die zugehörige Codierungsfunktion zu verwenden?
zzzzBov
Ich habe 6 Stunden damit verbracht, alle möglichen Dinge mit Tonnen von Variationen auszuprobieren, nur um einen winzigen zusätzlichen Schrägstrich zu entdecken, der alles wie Magie funktionieren lässt. Die Dinge, die ich für hart hielt, dauerten 5 Minuten. Das, was ich für gegeben hielt, wurde unmöglich. .omg
Muhammad Umer
1
Wenn Sie Ajax-Aufrufe mit serverseitigem PHP-DB-Speichern verwenden, verwenden Sie einfach die PHP-Funktion Addslashes (), um sie zu konvertieren. Mit dieser Lösung haben Sie nur einen Ort zum Konvertieren und es ist sauberer als die Javascript-Ersetzungszeilen.
Marcel Ennix

Antworten:

134

Nehmen Sie Ihren JSON und .stringify()es. Verwenden Sie dann die .replace()Methode und ersetzen Sie alle Vorkommen von \ndurch \\n.

BEARBEITEN:

Soweit mir bekannt ist, gibt es keine bekannten JS-Bibliotheken, um alle Sonderzeichen in einer Zeichenfolge zu maskieren. Sie können die .replace()Methode jedoch verketten und alle Sonderzeichen wie folgt ersetzen:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.replace(/\\n/g, "\\n")
                                      .replace(/\\'/g, "\\'")
                                      .replace(/\\"/g, '\\"')
                                      .replace(/\\&/g, "\\&")
                                      .replace(/\\r/g, "\\r")
                                      .replace(/\\t/g, "\\t")
                                      .replace(/\\b/g, "\\b")
                                      .replace(/\\f/g, "\\f");
// myEscapedJSONString is now ready to be POST'ed to the server. 

Aber das ist ziemlich böse, nicht wahr? Geben Sie die Schönheit von Funktionen ein, indem Sie damit Code in Teile zerlegen und den Hauptfluss Ihres Skripts sauber und frei von 8 verketteten .replace()Aufrufen halten können. Lassen Sie uns diese Funktionalität in eine Funktion namens , escapeSpecialChars(). Fahren wir fort und hängen Sie es an die prototype chaindes StringObjekts, also nennen wir können escapeSpecialChars()direkt auf String - Objekte.

Wie so:

String.prototype.escapeSpecialChars = function() {
    return this.replace(/\\n/g, "\\n")
               .replace(/\\'/g, "\\'")
               .replace(/\\"/g, '\\"')
               .replace(/\\&/g, "\\&")
               .replace(/\\r/g, "\\r")
               .replace(/\\t/g, "\\t")
               .replace(/\\b/g, "\\b")
               .replace(/\\f/g, "\\f");
};

Sobald wir diese Funktion definiert haben, ist der Hauptteil unseres Codes so einfach:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server
Alex
quelle
3
Danke alex. Ich muss das für alle Escape-Charaktere tun, oder? Gibt es eine JS-Bibliothek, um dies zu tun?
Srikant
2
Dies ist die genaue Funktion, die mein Problem gelöst hat. String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\\"). ersetzen (/ \ n / g, "\\ n"). ersetzen (/ \ r / g, "\\ r"). ersetzen (/ \ t / g, "\\ t"). ersetzen (/ \ f / g, "\\ f"). ersetzen (/ "/ g," \\\ ""). ersetzen (/ '/ g, "\\\'"). ersetzen (/ \ & / g, "\\ &"); }
Srikant
10
Wie in der Antwort von user667073 angegeben, weist diese Lösung einige Fehler auf. Siehe json.org - & und ' dürfen nicht maskiert werden.
Alexander Klimetschek
5
Ich musste dies ablehnen, da die regulären Ausdrücke falsch zu sein scheinen. Ich habe versucht, es zu verwenden, musste aber die regulären Ausdrücke korrigieren, indem ich einen der Schrägstriche entfernte, zum Beispiel: / \\ n / g sollte / \ n / g sein. Siehe "Nicht druckbare Zeichen" unter diesem Link für Details - RegExp Info
b01
1
was ist mit \ selbst? sollte das auch entkommen?
Arash Moeen
65

Wie vom Benutzer 667073 vorgeschlagen, außer dass zuerst der Backslash-Ersatz neu angeordnet und der Angebotsersatz korrigiert wird

escape = function (str) {
  return str
    .replace(/[\\]/g, '\\\\')
    .replace(/[\"]/g, '\\\"')
    .replace(/[\/]/g, '\\/')
    .replace(/[\b]/g, '\\b')
    .replace(/[\f]/g, '\\f')
    .replace(/[\n]/g, '\\n')
    .replace(/[\r]/g, '\\r')
    .replace(/[\t]/g, '\\t');
};
Ryan
quelle
3
Sie müssen nicht alle diese tun. Nur Backslash, Newline, Linefeed und die beiden Anführungszeichen. Und es fehlt: Einfaches Anführungszeichen Line separator \u2028und Paragraph separator \u2029. Ref: es5.github.io/#x7.3
Ariel
1
Schön, aber warum sind die eckigen Klammern notwendig und nicht: Escape = Funktion (str) {return str .replace (/ \\ / g, '\\\\') .replace (/ \ "/ g, '\\\ "') .replace (/ \ // g,' \\ / ') .replace (/ \ b / g,' \\ b ') .replace (/ \ f / g,' \\ f ') .replace (/ \ n / g, '\\ n') .replace (/ \ r / g, '\\ r') .replace (/ \ t / g, '\\ t'); };
Johann Echavarria
3
perfekt. Die akzeptierte Antwort (über dieser) funktioniert einfach nicht. mit nodeJS.
Yossi Shasho
Ich bekomme diesen Fehler:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros
31

Wie Sie habe ich mehrere Kommentare und Beiträge untersucht, um spezielle Escape-Zeichen in meinem JSON zu ersetzen, das darin ein HTML-Objekt enthält.

Mein Ziel ist es, die Sonderzeichen im JSON-Objekt zu entfernen und auch das HTML zu rendern, das sich im json-Objekt befindet.

Hier ist, was ich getan habe und hoffe, dass es sehr einfach zu bedienen ist.

Zuerst habe ich JSON.stringify für mein json-Objekt und JSON.parse das Ergebnis erstellt.

Zum Beispiel:

JSON.parse(JSON.stringify(jsonObject));

Und es löst mein Problem und erledigt mit Pure Javascript.

Balasubramani M.
quelle
4
Dies ist definitiv der
richtige
1
Dies ist definitiv der richtige Weg!
MartianE
1
Dies wird definitiv auf komplexen und großen Objekten mit stackoverflowFehler
brechen
1
Versuchen Sie es JSON.parse(JSON.stringify($("body")))in einer HTML-Datei mit Body und einigen Tabellen. $ ("body") ist ein Javascript-Objekt, aber stringify schlägt beim Parsen fehl.
AaA
Ich werde Ihre Anfrage überprüfen und zurücksetzen.
Balasubramani M
24

Ich habe Angst zu sagen, dass die Antwort von Alex ziemlich falsch ist, um es milde auszudrücken:

  • Einige Charaktere, denen Alex zu entkommen versucht, müssen überhaupt nicht entkommen (wie & und ');
  • \ b ist überhaupt nicht die Rücktaste, sondern eine Wortgrenzenübereinstimmung
  • Zeichen, die maskiert werden müssen, werden nicht behandelt.

Diese Funktion

escape = function (str) {
    // TODO: escape %x75 4HEXDIG ?? chars
    return str
      .replace(/[\"]/g, '\\"')
      .replace(/[\\]/g, '\\\\')
      .replace(/[\/]/g, '\\/')
      .replace(/[\b]/g, '\\b')
      .replace(/[\f]/g, '\\f')
      .replace(/[\n]/g, '\\n')
      .replace(/[\r]/g, '\\r')
      .replace(/[\t]/g, '\\t')
    ; };

scheint eine bessere Annäherung zu sein.

whaefelinger
quelle
5
Eigentlich sollten Sie die Reihenfolge ändern, um die umgekehrten Schrägstriche vor den doppelten Anführungszeichen zu ersetzen, sonst erhalten Sie \\\\ ". Außerdem sollte die Anführungszeichenzeile .replace (/ [\"] / g, '\\\ sein) "')
Ryan
10

Ein kleines Update für einfache Anführungszeichen

function escape (key, val) {
    if (typeof(val)!="string") return val;
    return val      
        .replace(/[\\]/g, '\\\\')
        .replace(/[\/]/g, '\\/')
        .replace(/[\b]/g, '\\b')
        .replace(/[\f]/g, '\\f')
        .replace(/[\n]/g, '\\n')
        .replace(/[\r]/g, '\\r')
        .replace(/[\t]/g, '\\t')
        .replace(/[\"]/g, '\\"')
        .replace(/\\'/g, "\\'"); 
}

var myJSONString = JSON.stringify(myJSON,escape);
Akash Dhawale
quelle
7

Dies ist ein alter Beitrag. Es kann jedoch weiterhin hilfreich sein, wenn Sie angle.fromJson und JSON.stringify verwenden. Escape () ist veraltet. Verwenden Sie dies stattdessen,

var uri_enc = encodeURIComponent(uri); //before you post the contents
var uri_dec = decodeURIComponent(uri_enc); //before you display/use the contents.

ref http://www.w3schools.com/jsref/jsref_decodeuricomponent.asp

Sam
quelle
stringify erledigt schon alles für dich - ich bin gespannt warum nicht einfach das nutzen? git.io/vglq7
Ben Davis
5

Es gibt auch einen zweiten Parameter in JSON.stringify. Eine elegantere Lösung wäre also:

function escape (key, val) {
    if (typeof(val)!="string") return val;
    return val
      .replace(/[\"]/g, '\\"')
      .replace(/[\\]/g, '\\\\')
      .replace(/[\/]/g, '\\/')
      .replace(/[\b]/g, '\\b')
      .replace(/[\f]/g, '\\f')
      .replace(/[\n]/g, '\\n')
      .replace(/[\r]/g, '\\r')
      .replace(/[\t]/g, '\\t')
    ; 
}

var myJSONString = JSON.stringify(myJSON,escape);
Krunoslav Djakovic
quelle
5

Dies ist eine alte Frage, aber die Lösung hat bei mir nicht gut funktioniert, da sie nicht alle Fälle gelöst hat. Ich habe endlich eine Antwort gefunden, die hier funktioniert hat

Ich werde meine kombinierte Lösung aus Escape und Codierung der Uri-Komponente veröffentlichen:

// implement JSON stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
    var t = typeof (obj);
    if (t != "object" || obj === null) {
        // simple data type
        if (t == "string") obj = '"'+obj+'"';
        return String(obj);
    }
    else {
        // recurse array or object
        var n, v, json = [], arr = (obj && obj.constructor == Array);
        for (n in obj) {
            v = obj[n]; t = typeof(v);
            if (t == "string") v = '"'+v+'"';
            else if (t == "object" && v !== null) v = JSON.stringify(v);
            json.push((arr ? "" : '"' + n + '":') + String(v));
        }
        var rawString = (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
       return rawString;
    }
};
function escape (key, val) {
    if (typeof(val)!="string") return val;

    var replaced = encodeURIComponent(val);
    return replaced;
}

JSON.stringifyEscaped = function(obj){
    return JSON.stringify(obj,escape);
}
Mitzi
quelle
Vielleicht entfernen Sie danach auch die doppelten Anführungszeichen um die Zeichenfolge? escape = (string) -> JSON.stringify(string)[1...-1]
Radek
3

Es ist besser zu benutzen JSON.parse(yourUnescapedJson);

Mohit Vachhani
quelle
3

Verwenden Sie json_encode (), wenn Ihre serverseitige Skriptsprache PHP ist, json_encode()der Zeilenumbruch und andere unerwartete Token für Sie nicht angezeigt werden ( wenn Sie PHP nicht verwenden, suchen Sie nach ähnlichen Funktionen für Ihre Skriptsprache).

dann $.parseJSON()in deinem JavaScript verwenden, fertig!

avngr
quelle
Wenn Sie Daten von PHP als JSON-Zeichenfolge an Javascript übergeben, überprüfen Sie diese Antwort - doppeltes Escapezeichen - hat mir geholfen, JSON.parse zu übergeben und die JSON-Zeichenfolge in ein Objekt zu konvertieren. <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> php JSON.parse Doppelcodierung
Vladimir Vukanac
2

Ich habe die gleiche Situation bei einem meiner Ajax-Aufrufe erhalten, bei dem JSONaufgrund der neuen Zeile im Feld Textarea ein Fehler aufgetreten ist. Die hier angegebene Lösung hat bei mir nicht funktioniert. Also habe ich die .escapeFunktion von Javascript verwendet und es hat gut funktioniert. JSONUm dann den Wert von abzurufen , habe ich einfach mit entkommen .unescape.

Anubhav Trivedi
quelle
Bei Ajax-Aufrufen bevorzuge ich die PHP-Funktion newStr = addiert Schrägstriche (str) und speichere dann in db. Ich muss also nicht auf Javascript- (Client-) Seite konvertieren. Mit dieser Lösung benötigen Sie nur einen Ort, um die Schrägstriche zu konvertieren. Ich bin sehr zufrieden mit dieser Lösung.
Marcel Ennix
2

Ich habe das eingebaute jQuery.serialize () verwendet , um den Wert aus einem Textbereich zu extrahieren und die Eingabe zu urlencodieren. Der Pro-Teil ist, dass Sie nicht suchen müssen, um jedes Sonderzeichen selbst zu ersetzen, und ich behalte auch die Zeilenumbrüche und entkomme HTML. Damit die Serialisierung funktioniert, muss das Eingabefeld anscheinend ein Namensattribut haben, und es fügt der Escapezeichenfolge, die ersetzt werden muss, dasselbe Attribut hinzu. Könnte nicht das sein, wonach Sie suchen, aber es funktioniert für mich.

var myinputfield = jQuery("#myinputfield"); 
var text = myinputfield.serialize();
text = text.replace(myinputfield.attr('name') + '=','');
Janspeed
quelle
1

Bei Verwendung einer beliebigen Form von Ajax scheint im Web eine detaillierte Dokumentation zum Format der vom CGI-Server empfangenen Antworten zu fehlen. Einige Einträge hier weisen darauf hin, dass Zeilenumbrüche in zurückgegebenen Text- oder JSON-Daten maskiert werden müssen, um Endlosschleifen (Hangs) bei der JSON-Konvertierung (möglicherweise durch Auslösen einer nicht erfassten Ausnahme) zu verhindern, unabhängig davon, ob dies automatisch durch jQuery oder manuell mithilfe des JSON-Parsing des Javascript-Systems oder der Bibliothek erfolgt Anrufe.

In jedem Fall, in dem Programmierer dieses Problem veröffentlichen, werden unzureichende Lösungen vorgestellt (meistens wird \ n auf der sendenden Seite durch \\ n ersetzt), und die Angelegenheit wird verworfen. Ihre Unzulänglichkeit wird beim Übergeben von Zeichenfolgenwerten aufgedeckt, in die versehentlich Steuerelement-Escape-Sequenzen eingebettet sind, z. B. Windows-Pfadnamen. Ein Beispiel ist "C: \ Chris \ Roberts.php", das die Steuerzeichen ^ c und ^ r enthält, was zu einer JSON-Konvertierung der Zeichenfolge {"file": "C: \ Chris \ Roberts.php"} in führen kann Schleife für immer. Eine Möglichkeit, solche Werte zu generieren, besteht darin, absichtlich zu versuchen, PHP-Warnungen und Fehlermeldungen vom Server an den Client zu übergeben. Dies ist eine vernünftige Idee.

Per Definition verwendet Ajax hinter den Kulissen HTTP-Verbindungen. Solche Verbindungen übertragen Daten mithilfe von GET und POST. Beide erfordern die Codierung der gesendeten Daten, um eine falsche Syntax einschließlich Steuerzeichen zu vermeiden.

Dies gibt genug Hinweise, um eine Lösung zu konstruieren (es müssen weitere Tests durchgeführt werden): Verwenden Sie Rawurlencode auf der PHP-Seite (Senden), um die Daten zu codieren, und Entweichen auf der Javascript-Seite (Empfangen), um die Daten zu decodieren. In einigen Fällen wenden Sie diese auf ganze Textzeichenfolgen an, in anderen Fällen wenden Sie sie nur auf Werte in JSON an.

Wenn sich diese Idee als richtig herausstellt, können einfache Beispiele erstellt werden, die Programmierern auf allen Ebenen helfen, dieses Problem ein für alle Mal zu lösen.

David Spector
quelle
0

Sieht so aus, als wäre dies wirklich ein alter Beitrag :-) Aber Leute, die beste Lösung, die ich dafür habe, um 100% zu sein, dass es ohne komplizierten Code funktioniert, besteht darin, beide Funktionen des Codierens / Decodierens für base64 zu verwenden. Dies sind atob () und btoa (). Bei weitem der einfachste und beste Weg, keine Sorge zu machen, wenn Sie irgendwelche Charaktere verpasst haben, denen Sie entkommen können.

George

Giorgoc
quelle
Da habe ich mir die gleiche Lösung ausgedacht. Ich frage mich, ob jemand diese Lösung klären könnte und ob es einige versteckte Vorbehalte gibt. Vielen Dank.
Mahish
0

Wenn Ihre Googles Sie weiterhin hier landen und Ihre API Fehler auslöst, es sei denn, Ihre JSON-Anführungszeichen werden "{\"foo\": true}"maskiert ( ), müssen Sie nur zweimal stringifizieren, zJSON.stringify(JSON.stringify(bar))

Avolition
quelle
-1

Verwenden Sie encodeURIComponent (), um die Zeichenfolge zu codieren.

Z.B. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

Sie müssen es nicht dekodieren, da der Webserver automatisch dasselbe tut.

Sanju Kaniyamattam
quelle
-8

Verwenden Sie niemals reguläre Ausdrücke (ich meine wie nie zuvor). Der beste und effektivste Weg:

String.prototype.escapeJSON = function() {
    var result = "";
    for (var i = 0; i < this.length; i++)
    {
        var ch = this[i];
        switch (ch)
        {
            case "\\": ch = "\\\\"; break;
            case "\'": ch = "\\'"; break;
            case "\"": ch = '\\"'; break;
            case "\&": ch = "\\&"; break;
            case "\t": ch = "\\t"; break;
            case "\n": ch = "\\n"; break;
            case "\r": ch = "\\r"; break;
            case "\b": ch = "\\b"; break;
            case "\f": ch = "\\f"; break;
            case "\v": ch = "\\v"; break;
            default: break;
        }

        result += ch;
    }

    return result;
};
Alek Depler
quelle
Sie können nicht sagen: "Verwenden Sie niemals reguläre Ausdrücke (ich meine wie nie zuvor)." Jedes Werkzeug erfüllt seinen Zweck.
14.
Ihre Antwort ist gültig, Sie haben sie nur mit hoher Meinung ausgedrückt, was insbesondere bei Junioren zu Verwirrung führen kann.
Zstate
@oncode reguläre Ausdrücke sind unglaublich nutzlos, egal wie und wann sie verwendet werden sollen. Dies führt nur zu undefiniertem Verhalten und zur Verschwendung von CPU-Zeit.
Alek Depler