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.


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

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

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.


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.


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

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


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

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

Może później usuń również podwójne cudzysłowy wokół ciągu? escape = (string) -> JSON.stringify(string)[1...-1]
Radek


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!


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.


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') + '=','');

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.


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


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


-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.


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.