Come sfuggire a una stringa JSON contenente caratteri di nuova riga usando JavaScript?


166

Devo formare una stringa JSON in cui un valore ha un nuovo carattere di linea. Questo deve essere evitato e quindi pubblicato utilizzando la chiamata AJAX. Qualcuno può suggerire un modo per sfuggire alla stringa con JavaScript. Non sto usando jQuery.


1
Ho provato a sfuggire al nuovo carattere di linea \ n in \\ n. Funziona benissimo. Ma sto cercando una libreria JS che possa farlo per tutti i personaggi di escape.
Srikant,

1
Perché è necessario sfuggire alle nuove righe all'interno di JSON? Come vengono decodificati questi valori quando vengono utilizzati, perché la soluzione appropriata è utilizzare la relativa funzione di codifica.
zzzzBov,

ho trascorso 6 ore a provare ogni genere di cose con tonnellate di variazioni solo per scoprire che una piccola barra aggiuntiva avrebbe fatto funzionare tutto come per magia, le cose che pensavo fossero difficili impiegavano 5 minuti ... la cosa che pensavo fosse stata data è diventata impossibile. .omg
Muhammad Umer

1
Quando usi le chiamate Ajax con il salvataggio sul lato server di php-db, usa semplicemente la funzione php ADDLASH () per convertirlo. Con questa soluzione hai solo un posto da convertire ed è più pulito delle linee di sostituzione javascript.
Marcel Ennix,

Risposte:


134

Prendi il tuo JSON e .stringify()lo fa. Quindi utilizzare il .replace()metodo e sostituire tutte le occorrenze di \ncon \\n.

MODIFICARE:

Per quanto ne so, non ci sono librerie JS ben note per sfuggire a tutti i caratteri speciali in una stringa. Tuttavia, potresti concatenare il .replace()metodo e sostituire tutti i caratteri speciali in questo modo:

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. 

Ma è piuttosto brutto, vero? Inserisci la bellezza delle funzioni, in quanto ti consentono di dividere il codice in pezzi e mantenere pulito il flusso principale del tuo script e liberare 8 .replace()chiamate concatenate . Quindi cerchiamo di mettere tale funzionalità in una funzione chiamata, escapeSpecialChars(). Andiamo avanti e alleghiamo prototype chainl' Stringoggetto dell'oggetto, in modo da poter chiamare escapeSpecialChars()direttamente sugli oggetti String.

Così:

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

Una volta definita quella funzione, il corpo principale del nostro codice è semplice come questo:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server

3
Grazie alex. Devo farlo per tutti i personaggi di fuga giusto? Esiste una libreria JS per farlo?
Srikant,

2
Questa è la funzione esatta che ha risolto il mio problema String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\\"). sostituisci (/ \ n / g, "\\ n"). sostituisci (/ \ r / g, "\\ r"). sostituisci (/ \ t / g, "\\ t"). sostituisci (/ \ f / g, "\\ f"). sostituire (/ "/ g," \\\ ""). sostituire (/ '/ g, "\\\'"). sostituisci (/ \ & / g, "\\ &"); }
Srikant il

10
Come notato nella risposta dell'utente667073, ci sono alcuni errori in questa soluzione. Vedi json.org - & e ' da non sfuggire.
Alexander Klimetschek,

5
Ho dovuto sottovalutare questo dato che le espressioni regolari sembrano essere sbagliate. Ho provato a usarlo, ma ho dovuto correggere le espressioni regolari rimuovendo una delle barre, ad esempio: / \\ n / g dovrebbe essere / \ n / g. Vedi "Personaggi non stampabili" a questo link per dettagli - RegExp Info
b01

1
che dire \ stesso? anche questo dovrebbe essere evaso?
arash moeen,

65

Come suggerito dall'utente667073, tranne riordinare prima la sostituzione della barra rovesciata e correggere la sostituzione del preventivo

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

3
Non devi fare tutto questo. Solo barra rovesciata, newline, linefeed e le due virgolette. E manca: virgoletta singola Line separator \u2028e Paragraph separator \u2029. Rif: es5.github.io/#x7.3
Ariel,

1
Bello, ma perché sono necessarie le parentesi quadre e non: 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'); };
Johann Echavarria,

3
Perfetto. la risposta accettata (sopra questa) semplicemente non funziona. usando nodeJS.
Yossi Shasho,

Ottengo questo errore:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros

32

Come te, ho esaminato diversi commenti e post per sostituire i caratteri di escape speciali nel mio JSON che contiene oggetti HTML all'interno.

Il mio oggetto è rimuovere i caratteri speciali nell'oggetto JSON e renderizzare anche l'html che si trova all'interno dell'oggetto json.

Ecco cosa ho fatto e spero che sia molto semplice da usare.

Per prima cosa ho fatto JSON.stringify il mio oggetto json e JSON.parse il risultato.

Ad esempio:

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

E risolve il mio problema e fatto usando Pure Javascript.


4
Questa è sicuramente la strada da percorrere
Oz Lodriguez,

1
Questa è sicuramente la strada da percorrere!
MartianE

1
Questo si romperà sicuramente su oggetti complessi e di grandi dimensioni con stackoverflowerrore
AaA,

1
prova JSON.parse(JSON.stringify($("body")))in un file html con body e alcune tabelle. $ ("body") è un oggetto javascript ma stringify non riuscirà ad analizzarlo.
AaA

Controllerò la tua richiesta e ripristinerò.
Balasubramani M,

24

Ho paura di dire che la risposta data da Alex è piuttosto errata, per dirla in parole povere:

  • Alcuni personaggi che Alex tenta di scappare non sono obbligati a scappare (come & e ');
  • \ b non è affatto il carattere backspace ma piuttosto una corrispondenza del limite di parole
  • I personaggi che devono essere salvati non vengono gestiti.

Questa funzione

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

sembra essere una migliore approssimazione.


5
in realtà dovresti cambiare l'ordine per sostituire le barre rovesciate prima delle doppie virgolette, altrimenti finirai con \\\\ ". Anche la riga delle virgolette dovrebbe essere .replace (/ [\"] / g, '\\\ "')
Ryan,

10

Un piccolo aggiornamento per virgolette singole

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

7

questo è un vecchio post. ma può ancora essere utile per coloro che usano angular.fromJson e JSON.stringify. escape () è deprecato. usa questo invece,

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


stringify già fa tutte le evasioni per te - sono curioso perché non usarlo? git.io/vglq7
Ben Davis

5

C'è anche un secondo parametro su JSON.stringify. Quindi, la soluzione più elegante sarebbe:

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

5

Questa è una vecchia domanda ma la soluzione non ha funzionato bene per me in quanto non ha risolto tutti i casi. Ho finalmente trovato una risposta che ha fatto il lavoro qui

Pubblicherò la mia soluzione combinata utilizzando sia il componente escape che codifica uri:

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

Magari rimuovi anche le doppie virgolette attorno alla stringa? escape = (string) -> JSON.stringify(string)[1...-1]
Radek,


3

Usa json_encode () se il tuo lang di scripting lato server è PHP, json_encode() sfugge alla nuova riga e ad altri token imprevisti per te (se non usi PHP cerca una funzione simile per il tuo linguaggio di scripting)

quindi utilizzare $.parseJSON()nel tuo JavaScript, fatto!


Se il passaggio di dati da PHP a JavaScript come stringa JSON, controlla questa risposta - doppio escape, mi ha aiutato a passare JSON.parse e convertire la stringa JSON in oggetto. <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> php JSON.parse doppia codifica
Vladimir Vukanac,

2

Ho avuto la stessa situazione in una delle mie chiamate Ajax, dove JSONstava generando un errore a causa della nuova riga nel campo Textarea. La soluzione fornita qui non ha funzionato per me. Quindi ho usato la .escapefunzione Javascript e ha funzionato bene. Quindi, per recuperare il valore JSON, ho appena eseguito l'escaping usando .unescape.


Usando le chiamate Ajax, preferisco usare la funzione php newStr = importslashes (str), quindi salvare su db. Quindi non devo convertirmi sul lato javascript (client). Con questa soluzione è necessario un solo posto per convertire le barre. Sono molto contento di questa soluzione.
Marcel Ennix,

2

Ho usato il jQuery.serialize () incorporato per estrarre il valore da una textarea per urlencode l'input. La parte pro è che non devi cercare di sostituire ogni carattere speciale da solo e mantengo anche le nuove righe e sfugge a HTML. Perché la serializzazione funzioni sembra che il campo di input debba avere un attributo name e aggiunge anche lo stesso attributo alla stringa di escape che deve essere sostituita. Potrebbe non essere quello che stai cercando, ma funziona per me.

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

1

Quando si utilizza qualsiasi forma di Ajax, la documentazione dettagliata per il formato delle risposte ricevute dal server CGI sembra mancare sul Web. Alcune voci sottolineano che le righe di testo restituito o i dati json restituiti devono essere salvati per evitare loop infiniti (blocchi) nella conversione JSON (eventualmente creati generando un'eccezione non rilevata), sia eseguiti automaticamente da jQuery o manualmente utilizzando il sistema Javascript o l'analisi JSON della libreria chiamate.

In ogni caso in cui i programmatori presentano questo problema, vengono presentate soluzioni inadeguate (il più delle volte sostituiscono \ n con \\ n sul lato di invio) e la questione viene eliminata. La loro inadeguatezza viene rivelata quando si passano valori di stringa che incorporano accidentalmente sequenze di escape di controllo, come i percorsi di Windows. Un esempio è "C: \ Chris \ Roberts.php", che contiene i caratteri di controllo ^ c e ^ r, che possono causare la conversione JSON della stringa {"file": "C: \ Chris \ Roberts.php"} in loop per sempre. Un modo per generare tali valori è deliberatamente tentare di trasmettere messaggi di avviso e di errore PHP dal server al client, un'idea ragionevole.

Per definizione, Ajax utilizza connessioni HTTP dietro le quinte. Tali connessioni passano i dati utilizzando GET e POST, entrambi i quali richiedono la codifica dei dati inviati per evitare una sintassi errata, inclusi i caratteri di controllo.

Questo dà abbastanza un suggerimento per costruire quella che sembra essere una soluzione (ha bisogno di più test): usare rawurlencode sul lato PHP (invio) per codificare i dati, e annullare la scansione sul lato Javascript (ricezione) per decodificarli. In alcuni casi, le applicherai a intere stringhe di testo, in altri casi le applicherai solo ai valori all'interno di JSON.

Se questa idea risulta corretta, possono essere costruiti semplici esempi per aiutare i programmatori a tutti i livelli a risolvere questo problema una volta per tutte.


0

Sembra davvero che questo sia un post antico :-) Ma ragazzi, la migliore soluzione che ho per questo, essere al 100% che funzioni senza codice complicato, è usare entrambe le funzioni di codifica / decodifica su base64. Questi sono atob () e btoa (). Di gran lunga il modo più semplice e migliore, non devi preoccuparti se hai perso qualche personaggio da sfuggire.

Giorgio


Da quando ho trovato la stessa soluzione. Mi chiedo se qualcuno potrebbe chiarire questa soluzione e se ci sono alcuni avvertimenti nascosti. Grazie.
Mahish,

0

Se i tuoi Google continuano a farti atterrare qui e l'api genera errori a meno che le doppie virgolette JSON "{\"foo\": true}"non siano salvate ( ), tutto ciò che devi fare è stringere due volte ad es.JSON.stringify(JSON.stringify(bar))


-1

Utilizzare encodeURIComponent () per codificare la stringa.

Per esempio. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

Non è necessario decodificarlo poiché il server Web fa automaticamente lo stesso.


-8

Non usare mai espressioni regolari (intendo come mai). Il modo migliore ed efficace:

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

Non puoi dire "Non usare mai espressioni regolari (intendo come mai)". Ogni strumento ha il suo scopo.
zstate,

La tua risposta è valida, l'hai appena espressa in modo altamente supponente, il che potrebbe creare confusione, soprattutto per i giovani.
zstate,

Le espressioni regolari di @oncode sono incredibilmente inutili, non importa come e quando usarle. Porta solo a comportamenti indefiniti e spreca tempo della CPU.
Alek Depler,
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.