Jak uciec przed ciągiem JSON zawierającym znaki nowej linii za pomocą JavaScript?

166

Muszę utworzyć ciąg JSON, w którym wartość ma znak nowego wiersza. To musi zostać usunięte, a następnie wysłane za pomocą połączenia AJAX. Czy ktoś może zasugerować sposób na uniknięcie ciągu za pomocą JavaScript. Nie używam jQuery.

Srikant
źródło
1
Próbowałem zmienić znak nowej linii \ n na \\ n. Działa dobrze. Ale szukam dowolnej biblioteki JS, która może to zrobić dla wszystkich znaków ucieczki.
Srikant
1
Dlaczego musisz uciec od nowych linii w JSON? W jaki sposób te wartości są dekodowane, gdy są używane, ponieważ odpowiednim rozwiązaniem jest użycie powiązanej funkcji kodowania.
zzzzBov
Spędziłem 6 godzin próbując różnych rzeczy z mnóstwem wariacji, tylko po to, aby odkryć, że małe dodatkowe cięcie sprawi, że wszystko będzie działać jak magia, rzeczy, które uważałem za trudne, zajęły 5 minut ... to, co myślałem, że zostało dane, stało się niemożliwe. .omg
Muhammad Umer
1
Kiedy używasz wywołań Ajax z zapisywaniem php-db-po stronie serwera, po prostu użyj funkcji php addedlashes (), aby ją przekonwertować. Dzięki temu rozwiązaniu masz tylko jedno miejsce do konwersji i jest ono czystsze niż wiersze zastępowania javascript.
Marcel Ennix,

Odpowiedzi:

135

Weź swój JSON i .stringify()to. Następnie za pomocą .replace()metody i zastąpić wszystkie wystąpienia \nz \\n.

EDYTOWAĆ:

O ile mi wiadomo, nie ma dobrze znanych bibliotek JS do unikania wszystkich znaków specjalnych w ciągu. Ale możesz połączyć .replace()metodę i zastąpić wszystkie znaki specjalne w następujący sposób:

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. 

Ale to dość paskudne, prawda? Wprowadź piękno funkcji, ponieważ pozwalają one na rozbicie kodu na części i utrzymanie głównego przepływu skryptu w czystości i bez 8 połączonych .replace()wywołań. Więc postawmy tę funkcjonalność do funkcji o nazwie, escapeSpecialChars(). Idziemy do przodu i dołączyć go do prototype chaintego Stringobiektu, więc możemy wywołać escapeSpecialChars()bezpośrednio na obiektach String.

Tak jak to:

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

Po zdefiniowaniu tej funkcji główna część naszego kodu jest tak prosta:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server
Alex
źródło
3
Dzięki Alex. Muszę to zrobić dla wszystkich postaci ucieczki, prawda? Czy jest do tego jakaś biblioteka JS?
Srikant
2
To jest dokładna funkcja, która rozwiązała mój problem String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\\"). replace (/ \ n / g, „\\ n”). replace (/ \ r / g, "\\ r"). replace (/ \ t / g, „\\ t”). replace (/ \ f / g, "\\ f"). replace (/ „/ g,„ \\\ ””). replace (/ '/ g, "\\\'"). replace (/ \ & / g, „\\ &”); }
Srikant
10
Jak zauważyłem w odpowiedzi użytkownika667073, w tym rozwiązaniu jest kilka błędów. Zobacz json.org - & i ' nie mogą zostać zmienione .
Alexander Klimetschek
5
Musiałem głosować w dół, ponieważ wyrażenia regularne wydają się być błędne. Próbowałem go użyć, ale musiałem naprawić wyrażenia regularne, usuwając jeden z ukośników, na przykład: / \\ n / g powinno być / \ n / g. Aby uzyskać szczegółowe informacje,
b01
1
co z samym sobą? czy też należy uciec?
arash moeen
65

Zgodnie z sugestią użytkownika667073, z wyjątkiem zmiany kolejności zamiany ukośnika odwrotnego w pierwszej kolejności i naprawienia zamiany oferty

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
źródło
3
Nie musisz tego wszystkiego robić. Tylko ukośnik odwrotny, znak nowej linii, znak końca wiersza i dwa cudzysłowy. Brakuje: pojedynczy cudzysłów Line separator \u2028i Paragraph separator \u2029. Ref: es5.github.io/#x7.3
Ariel
1
Ładnie, ale dlaczego nawiasy kwadratowe są konieczne, a nie: 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
idealny. zaakceptowana odpowiedź (powyżej tej) po prostu nie działa. przy użyciu nodeJS.
Yossi Shasho
Otrzymuję ten błąd:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros,
32

Podobnie jak ty, przeglądałem kilka komentarzy i postów, aby zamienić specjalne znaki ucieczki w moim JSON, który zawiera w sobie obiekt HTML.

Moim celem jest usunięcie znaków specjalnych z obiektu JSON, a także renderowanie html, który znajduje się wewnątrz obiektu json.

Oto, co zrobiłem i mam nadzieję, że jest to bardzo proste w użyciu.

Najpierw zrobiłem JSON.stringify mój obiekt json i JSON.parse wynik.

Na przykład:

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

I rozwiązuje mój problem i zostało zrobione przy użyciu czystego JavaScript.

Balasubramani M
źródło
4
To jest zdecydowanie droga
Oz Lodriguez
1
To zdecydowanie najlepsza droga!
MarsjanE
1
To z pewnością zepsuje się w przypadku złożonych i dużych obiektów z stackoverflowbłędem
AaA
1
spróbuj JSON.parse(JSON.stringify($("body")))w pliku html z treścią i kilkoma tabelami. $ ("body") jest obiektem javascript, ale metoda stringify nie powiedzie się podczas jego analizy.
AaA
Sprawdzę Twoje zapytanie i powrócę.
Balasubramani M
24

Obawiam się powiedzieć, że odpowiedź udzielona przez Alexa jest raczej błędna, delikatnie mówiąc:

  • Niektóre postacie, które Alex próbuje uciec, nie muszą w ogóle uciekać (np. & I ');
  • \ b wcale nie jest znakiem cofania, ale raczej dopasowaniem granicy słowa
  • Znaki wymagane do ucieczki nie są obsługiwane.

Ta funkcja

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

wydaje się być lepszym przybliżeniem.

Whaefelinger
źródło
5
w rzeczywistości powinieneś zmienić kolejność, aby zastąpić ukośniki odwrotne przed cudzysłowami, w przeciwnym razie otrzymasz \\\\ ". Również wiersz cudzysłowu powinien mieć postać .replace (/ [\"] / g, '\\\ "')
Ryan
10

Mała aktualizacja dla pojedynczych cudzysłowów

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
źródło
7

to jest stary post. ale nadal może być pomocne dla osób używających angular.fromJson i JSON.stringify. escape () jest przestarzały. użyj tego zamiast tego,

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
źródło
stringify już wykonuje dla Ciebie wszystkie ucieczki - jestem ciekaw, dlaczego po prostu tego nie użyć? git.io/vglq7
Ben Davis
5

Istnieje również drugi parametr w JSON.stringify. Tak więc bardziej eleganckim rozwiązaniem byłoby:

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
źródło
5

To stare pytanie, ale rozwiązanie nie działało dobrze, ponieważ nie rozwiązało wszystkich przypadków. W końcu znalazłem odpowiedź, że spełnił swoje zadanie tutaj

Opublikuję moje połączone rozwiązanie wykorzystujące zarówno ucieczkę, jak i kodowanie komponentu 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);
}
Mitzi
źródło
Może później usuń również podwójne cudzysłowy wokół ciągu? escape = (string) -> JSON.stringify(string)[1...-1]
Radek
3

Lepiej go używać JSON.parse(yourUnescapedJson);

Mohit Vachhani
źródło
3

Użyj json_encode (), jeśli język skryptów po stronie serwera to PHP, json_encode()ucieka znak nowej linii i inne nieoczekiwane tokeny (jeśli nie używasz PHP, poszukaj podobnej funkcji dla swojego języka skryptowego)

następnie użyj $.parseJSON()w swoim JavaScript, gotowe!

avngr
źródło
Jeśli przekazujesz dane z php do javascript jako ciąg JSON, sprawdź tę odpowiedź - podwójne ucieczki, pomogły mi przekazać JSON.parse i przekonwertować ciąg JSON na obiekt. <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> php JSON.parse podwójne kodowanie
Vladimir Vukanac
2

Mam taką samą sytuację w jednym z moich wywołań Ajax, gdzie JSONwyrzucałem błąd z powodu nowej linii w polu Textarea. Podane tutaj rozwiązanie nie zadziałało. Więc użyłem .escapefunkcji Javascript i działało dobrze. Następnie, aby pobrać wartość JSON, po prostu cofnąłem zmianę za pomocą .unescape.

Anubhav Trivedi
źródło
Korzystając z wywołań Ajax, wolę używać funkcji php newStr = addedlashes (str), a następnie zapisać do bazy danych. Więc nie muszę konwertować po stronie javascript- (klienta). Dzięki temu rozwiązaniu potrzebujesz tylko jednego miejsca do konwersji ukośników. Jestem bardzo zadowolony z tego rozwiązania.
Marcel Ennix,
2

Użyłem wbudowanej funkcji jQuery.serialize (), aby wyodrębnić wartość z obszaru tekstowego, aby urlencode wprowadzić dane wejściowe. Zaletą jest to, że nie musisz samodzielnie wyszukiwać i zastępować wszystkich znaków specjalnych, a ja również zachowuję znaki nowej linii i znaki ucieczki w html. Aby serializacja działała, wydaje się, że pole wejściowe musi mieć atrybut nazwy, a także dodaje ten sam atrybut do ciągu znaków ucieczki, który należy zastąpić. Może nie być tym, czego szukasz, ale dla mnie działa.

var myinputfield = jQuery("#myinputfield"); 
var text = myinputfield.serialize();
text = text.replace(myinputfield.attr('name') + '=','');
Janspeed
źródło
1

Podczas korzystania z dowolnej formy Ajax w sieci WWW brakuje szczegółowej dokumentacji formatu odpowiedzi otrzymywanych z serwera CGI. Niektóre wpisy wskazują, że znaki nowej linii w zwracanym tekście lub danych json muszą zostać zmienione, aby zapobiec nieskończonym pętlom (zawieszeniom) w konwersji JSON (prawdopodobnie utworzonej przez wyrzucenie niepochwyconego wyjątku), niezależnie od tego, czy jest to wykonywane automatycznie przez jQuery, czy ręcznie przy użyciu systemu JavaScript lub analizy JSON biblioteki wezwania.

W każdym przypadku, gdy programiści publikują ten problem, przedstawiane są nieadekwatne rozwiązania (najczęściej zastępując \ n przez \\ n po stronie wysyłającej) i sprawa zostaje odrzucona. Ich nieadekwatność ujawnia się podczas przekazywania wartości ciągów, które przypadkowo osadzają sekwencje sterujące, takie jak nazwy ścieżek systemu Windows. Przykładem jest „C: \ Chris \ Roberts.php”, który zawiera znaki sterujące ^ c i ^ r, co może spowodować konwersję ciągu JSON ciągu {"file": "C: \ Chris \ Roberts.php"} na pętla na zawsze. Jednym ze sposobów generowania takich wartości jest celowa próba przekazywania ostrzeżeń PHP i komunikatów o błędach z serwera do klienta, co jest rozsądnym pomysłem.

Z definicji Ajax używa połączeń HTTP za kulisami. Takie połączenia przekazują dane za pomocą GET i POST, które wymagają kodowania wysyłanych danych, aby uniknąć nieprawidłowej składni, w tym znaków sterujących.

Daje to wystarczającą wskazówkę, aby skonstruować coś, co wydaje się być rozwiązaniem (wymaga więcej testów): użyć kodu rawurlen po stronie PHP (wysyłającej) do kodowania danych i unescape po stronie JavaScript (odbierającej) do dekodowania danych. W niektórych przypadkach zastosujesz je do całych ciągów tekstowych, w innych zastosujesz je tylko do wartości wewnątrz JSON.

Jeśli ten pomysł okaże się słuszny, można skonstruować proste przykłady, które pomogą programistom na wszystkich poziomach raz na zawsze rozwiązać ten problem.

David Spector
źródło
0

Wygląda na to, że to naprawdę starożytny post :-) Ale najlepsze obejście, jakie mam, aby to było w 100% działało bez skomplikowanego kodu, jest użycie obu funkcji kodowania / dekodowania do base64. Są to atob () i btoa (). Zdecydowanie najłatwiejszy i najlepszy sposób, nie musisz się martwić, jeśli przegapiłeś jakiekolwiek postacie, którym chcesz uciec.

Jerzy

Giorgoc
źródło
Odkąd wymyśliłem to samo rozwiązanie. Zastanawiam się, czy ktoś mógłby wyjaśnić to rozwiązanie i czy są jakieś ukryte zastrzeżenia. Dzięki.
mahish
0

Jeśli Twoje Google wciąż Cię tu lądują, a Twój interfejs API generuje błędy, chyba że podwójne cudzysłowy JSON są "{\"foo\": true}"oznaczone znakami ucieczki ( ), wszystko, co musisz zrobić, to dwukrotnie wpisać ciąg znaków, np.JSON.stringify(JSON.stringify(bar))

Avolition
źródło
-1

Użyj metody encodeURIComponent (), aby zakodować ciąg.

Na przykład. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

Nie musisz go dekodować, ponieważ serwer WWW robi to samo.

Sanju Kaniyamattam
źródło
-8

Nigdy nie używaj wyrażeń regularnych (mam na myśli jak nigdy). Najlepszy i skuteczny sposób:

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
źródło
Nie możesz powiedzieć: „Nigdy nie używaj wyrażeń regularnych (mam na myśli, jak nigdy)”. Każde narzędzie spełnia swoje zadanie.
zstate
Twoja odpowiedź jest ważna, po prostu wyraziłeś ją w bardzo uparty sposób, co może wywołać zamieszanie, zwłaszcza wśród juniorów.
zstate
Wyrażenia regularne @oncode są niesamowicie bezużyteczne, bez względu na to, jak i kiedy ich używać. Prowadzi tylko do nieokreślonego zachowania i marnowania czasu procesora.
Alek Depler