Bagaimana cara melepaskan diri dari string JSON yang berisi karakter baris baru menggunakan JavaScript?

166

Saya harus membentuk string JSON di mana nilai memiliki karakter baris baru. Ini harus lolos dan kemudian diposting menggunakan panggilan AJAX. Adakah yang bisa menyarankan cara untuk melarikan diri dari string dengan JavaScript. Saya tidak menggunakan jQuery.

Srikant
sumber
1
Saya mencoba keluar dari karakter baris baru \ n ke \\ n. Ini bekerja dengan baik. Tetapi saya sedang mencari perpustakaan JS yang dapat melakukan ini untuk semua karakter pelarian.
Srikant
1
Mengapa Anda perlu melarikan diri dari baris baru dalam JSON? Bagaimana nilai-nilai ini didekodekan ketika digunakan, karena solusi yang tepat adalah dengan menggunakan fungsi penyandian terkait
zzzzBov
Saya menghabiskan 6 jam mencoba segala macam hal dengan banyak variasi hanya untuk menemukan tebasan tambahan kecil akan membuat semuanya bekerja seperti sihir hal-hal yang saya pikir butuh waktu 5 menit ... hal yang saya pikir diberikan menjadi hal yang mustahil. .omg
Muhammad Umer
1
Ketika Anda menggunakan panggilan-Ajax dengan Server-side php-db-save, cukup gunakan php-function addlashes () untuk mengubahnya. Dengan solusi ini, Anda hanya memiliki satu tempat untuk dikonversi dan lebih bersih daripada garis ganti javascript.
Marcel Ennix

Jawaban:

134

Ambil JSON Anda dan .stringify()itu. Kemudian gunakan .replace()metode ini dan ganti semua kejadian \ndengan \\n.

EDIT:

Sejauh yang saya tahu, tidak ada perpustakaan JS terkenal untuk melarikan diri semua karakter khusus dalam sebuah string. Tetapi, Anda dapat membuat rantai .replace()metode dan mengganti semua karakter khusus seperti ini:

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. 

Tapi itu cukup jahat, bukan? Masukkan keindahan fungsi, karena memungkinkan Anda untuk memecah kode menjadi beberapa bagian dan menjaga alur utama skrip Anda bersih, dan bebas dari 8 .replace()panggilan berantai . Jadi mari kita letakkan fungsionalitas itu ke dalam fungsi yang disebut escapeSpecialChars(),. Mari kita pergi ke depan dan melampirkannya ke prototype chainsatu Stringobjek, sehingga kami dapat menghubungi escapeSpecialChars()langsung di String objek.

Seperti itu:

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

Setelah kami mendefinisikan fungsi itu, isi utama kode kami sesederhana ini:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server
Alex
sumber
3
Terima kasih, alex. Saya harus melakukan ini untuk semua karakter pelarian kan? Apakah ada perpustakaan JS untuk melakukan ini?
Srikant
2
Ini adalah fungsi persis yang memecahkan masalah saya String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\"). ganti (/ \ n / g, "\\ n"). ganti (/ \ r / g, "\\ r"). ganti (/ \ t / g, "\\ t"). ganti (/ \ f / g, "\\ f"). ganti (/ "/ g," \\ ""). ganti (/ '/ g, "\\\'"). ganti (/ \ & / g, "\\ &"); }
Srikant
10
Seperti dicatat dalam jawaban oleh user667073, ada beberapa kesalahan dalam solusi ini. Lihat json.org - & dan ' tidak boleh melarikan diri.
Alexander Klimetschek
5
Saya harus memilih ini karena ekspresi regulernya keliru. Saya mencoba menggunakannya, tetapi harus memperbaiki ekspresi reguler dengan menghapus salah satu garis miring, misalnya: / \\ n / g harus menjadi / \ n / g. Lihat "Karakter Tidak Dapat Dicetak" di tautan ini untuk detail - Info RegExp
b01
1
bagaimana dengan \ sendiri? haruskah itu juga diloloskan?
arash moeen
65

Sesuai dengan user667073 yang disarankan, kecuali menyusun ulang penggantian backslash terlebih dahulu, dan memperbaiki penggantian kutipan

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
sumber
3
Anda tidak harus melakukan semua ini. Hanya backslash, baris baru, umpan baris, dan dua kutipan. Dan itu hilang: Kutipan tunggal, Line separator \u2028dan Paragraph separator \u2029. Ref: es5.github.io/#x7.3
Ariel
1
Bagus, tetapi mengapa tanda kurung siku perlu dan tidak: escape = function (str) {return str .replace (/ \\ / g, '\\\') .replace (/ \ "/ g, '\\\ "') .replace (/ \ // g,' \\ / ') .replace (/ \ b / g,' \\ b ') .replace (/ \ f / g,' \\ f ') .replace (/ \ n / g, '\\ n'). ganti (/ \ r / g, '\\ r') .replace (/ \ t / g, '\\ t'); };
Johann Echavarria
3
sempurna. jawaban yang diterima (di atas ini) sama sekali tidak bekerja. menggunakan nodeJS.
Yossi Shasho
Saya mendapatkan kesalahan ini:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros
32

Seperti Anda, saya telah melihat beberapa komentar dan posting untuk mengganti karakter pelarian khusus di JSON saya yang berisi objek html di dalamnya.

Objek saya adalah menghapus karakter khusus dalam objek JSON dan juga me-render html yang ada di dalam objek json.

Inilah yang saya lakukan dan berharap sangat mudah digunakan.

Pertama saya melakukan JSON.stringify objek json saya dan JSON.parse hasilnya.

Untuk misalnya:

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

Dan itu memecahkan masalah saya dan selesai menggunakan Javascript Murni.

Balasubramani M
sumber
4
Ini jelas cara yang harus ditempuh
Oz Lodriguez
1
Ini jelas cara untuk pergi!
MartianE
1
Ini pasti akan merusak objek yang kompleks dan besar dengan stackoverflowkesalahan
AaA
1
coba JSON.parse(JSON.stringify($("body")))dalam file html dengan tubuh dan beberapa tabel. $ ("body") adalah objek javascript tetapi string akan gagal menguraikannya.
AaA
Saya akan memeriksa permintaan Anda dan mengembalikan.
Balasubramani M
24

Saya takut mengatakan bahwa jawaban yang diberikan oleh Alex agak salah, dengan kata lain:

  • Beberapa karakter yang dicoba Alex untuk melarikan diri tidak diharuskan untuk melarikan diri sama sekali (seperti & dan ');
  • \ b sama sekali bukan karakter backspace melainkan pertandingan batas kata
  • Karakter yang diperlukan untuk melarikan diri tidak ditangani.

Fungsi ini

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

tampaknya merupakan perkiraan yang lebih baik.

pedagang whaefelinger
sumber
5
sebenarnya Anda harus mengubah urutan untuk mengganti garis miring terbalik sebelum tanda kutip ganda, atau Anda akan berakhir dengan \\ ". Juga baris kutipan harus. ganti (/ [\"] / g, '\\\ "')
Ryan
10

Pembaruan kecil untuk kutipan tunggal

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

ini adalah pos lama. tetapi mungkin masih bermanfaat bagi mereka yang menggunakan angular.fromJson, dan JSON.stringify. escape () sudah usang. gunakan ini sebagai gantinya,

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
sumber
merangkai sudah melakukan semua pelarian untuk Anda - saya ingin tahu mengapa tidak hanya menggunakan itu? git.io/vglq7
Ben Davis
5

Ada juga parameter kedua di JSON.stringify. Jadi, solusi yang lebih elegan adalah:

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
sumber
5

Ini adalah pertanyaan lama tetapi solusinya tidak bekerja dengan baik bagi saya karena tidak menyelesaikan semua kasus. Saya akhirnya menemukan jawaban yang berhasil di sini

Saya akan memposting solusi gabungan saya baik menggunakan escape dan menyandikan komponen 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
sumber
Mungkin menghapus tanda kutip ganda di sekitar string sesudahnya juga? escape = (string) -> JSON.stringify(string)[1...-1]
Radek
3

Lebih baik digunakan JSON.parse(yourUnescapedJson);

Mohit Vachhani
sumber
3

Gunakan json_encode () jika bahasa skrip sisi server Anda adalah PHP, json_encode()lewati baris baru & token tak terduga lainnya untuk Anda (jika tidak menggunakan tampilan PHP untuk fungsi serupa untuk bahasa skrip Anda)

lalu gunakan $.parseJSON()di JavaScript Anda, selesai!

avngr
sumber
Jika meneruskan data dari php ke javascript sebagai string JSON, periksa jawaban ini - double escape, membantu saya meneruskan JSON.parse dan mengonversi string json ke objek. <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> php JSON.parse pengkodean ganda
Vladimir Vukanac
2

Saya mendapat situasi yang sama di salah satu panggilan Ajax saya, di mana JSONada kesalahan karena baris baru di bidang Textarea. Solusi yang diberikan di sini tidak berhasil untuk saya. Jadi saya menggunakan .escapefungsi Javascript dan bekerja dengan baik. Kemudian untuk mengambil nilai dari JSON, saya hanya menggunakan unescaped .unescape.

Anubhav Trivedi
sumber
Menggunakan panggilan Ajax, saya lebih suka menggunakan fungsi php newStr = addlashes (str), lalu simpan ke db. Jadi saya tidak perlu mengkonversi di javascript- (klien) -di samping. Dengan solusi ini Anda hanya perlu satu tempat untuk mengkonversi garis miring. Saya sangat senang dengan solusi ini.
Marcel Ennix
2

Saya menggunakan built in jQuery.serialize () untuk mengekstrak nilai dari textarea untuk urlencode input. Bagian pro adalah bahwa Anda tidak perlu mencari mengganti setiap karakter khusus Anda sendiri dan saya juga menjaga baris baru dan lolos dari html. Untuk membuat serialisasi agar berfungsi, tampaknya bidang input perlu memiliki atribut nama dan juga menambahkan atribut yang sama ke string yang lolos yang perlu diganti. Mungkin bukan yang Anda cari, tetapi itu bekerja untuk saya.

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

Ketika menggunakan segala bentuk Ajax, dokumentasi terperinci untuk format tanggapan yang diterima dari server CGI tampaknya kurang di Web. Beberapa entri di sini menunjukkan bahwa baris baru dalam teks yang dikembalikan atau data json harus melarikan diri untuk mencegah loop tak terbatas (hang) dalam konversi JSON (mungkin dibuat dengan melemparkan pengecualian yang tidak tertangkap), baik dilakukan secara otomatis oleh jQuery atau secara manual menggunakan sistem Javascript atau pustaka JSON pustaka panggilan.

Dalam setiap kasus di mana programmer memposting masalah ini, solusi yang tidak memadai disajikan (paling sering mengganti \ n oleh \ n di sisi pengiriman) dan masalah tersebut dibatalkan. Ketidakmampuan mereka terungkap ketika melewati nilai string yang secara tidak sengaja menanamkan urutan pelarian kendali, seperti nama path Windows. Contohnya adalah "C: \ Chris \ Roberts.php", yang berisi karakter kontrol ^ c dan ^ r, yang dapat menyebabkan konversi JSON dari string {"file": "C: \ Chris \ Roberts.php"} ke lingkaran selamanya. Salah satu cara untuk menghasilkan nilai-nilai tersebut adalah dengan sengaja mencoba untuk menyampaikan peringatan PHP dan pesan kesalahan dari server ke klien, ide yang masuk akal.

Menurut definisi, Ajax menggunakan koneksi HTTP di belakang layar. Koneksi tersebut meneruskan data menggunakan GET dan POST, yang keduanya membutuhkan pengodean data yang dikirim untuk menghindari sintaks yang salah, termasuk karakter kontrol.

Ini memberi cukup petunjuk untuk membangun apa yang tampaknya menjadi solusi (perlu pengujian lebih lanjut): untuk menggunakan rawurlencode pada sisi PHP (pengiriman) untuk menyandikan data, dan menghapus tanda pada sisi Javascript (penerima) untuk mendekode data. Dalam beberapa kasus, Anda akan menerapkan ini ke seluruh string teks, dalam kasus lain Anda hanya akan menerapkannya pada nilai-nilai di dalam JSON.

Jika ide ini ternyata benar, contoh-contoh sederhana dapat dibangun untuk membantu programmer di semua tingkatan menyelesaikan masalah ini untuk selamanya.

David Spector
sumber
0

Sepertinya ini adalah posting kuno benar-benar :-) Tapi teman-teman, solusi terbaik yang saya miliki untuk ini, menjadi 100% bekerja tanpa kode rumit, adalah dengan menggunakan kedua fungsi pengkodean / decoding ke base64. Ini adalah atob () dan btoa (). Sejauh ini cara termudah dan terbaik, tidak perlu khawatir jika Anda melewatkan karakter apa pun untuk melarikan diri.

George

Giorgoc
sumber
Karena saya datang dengan solusi yang sama. Saya ingin tahu apakah seseorang dapat mengklarifikasi solusi ini dan apakah ada beberapa peringatan yang tersembunyi. Terima kasih.
Mahish
0

Jika Googles Anda terus mendaratkan Anda di sini dan api Anda melontarkan kesalahan kecuali tanda kutip ganda JSON Anda lolos ( "{\"foo\": true}"), yang perlu Anda lakukan adalah meringkas dua kali misalnyaJSON.stringify(JSON.stringify(bar))

Avolition
sumber
-1

Gunakan encodeURIComponent () untuk menyandikan string.

Misalnya. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

Anda tidak perlu men-decode karena server web secara otomatis melakukan hal yang sama.

Sanju Kaniyamattam
sumber
-8

Jangan pernah menggunakan ekspresi reguler (maksud saya tidak pernah sama sekali). Cara terbaik dan efektif:

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
sumber
Anda tidak bisa mengatakan, "Jangan pernah menggunakan ekspresi reguler (maksud saya tidak pernah sama sekali)". Setiap alat melayani tujuannya.
zstate
Jawaban Anda valid, Anda hanya mengungkapkannya dengan cara yang sangat beralasan, yang dapat membuat kebingungan, terutama untuk junior.
zstate
@oncode ekspresi reguler tidak berguna, tidak peduli bagaimana dan kapan menggunakannya. Ini hanya menyebabkan perilaku yang tidak terdefinisi dan membuang-buang waktu CPU.
Alek Depler