จะหลีกเลี่ยงสตริง JSON ที่มีอักขระขึ้นบรรทัดใหม่โดยใช้ JavaScript ได้อย่างไร


166

ฉันต้องสร้างสตริง JSON ซึ่งค่าจะมีอักขระบรรทัดใหม่ สิ่งนี้จะต้องหลบหนีจากนั้นโพสต์โดยใช้การโทร AJAX คนใดคนหนึ่งสามารถแนะนำวิธีที่จะหลบหนีสตริงด้วย JavaScript ฉันไม่ได้ใช้ jQuery


1
ฉันพยายามหนีจากอักขระบรรทัดใหม่ \ n ไปที่ \\ n มันทำงานได้ดี แต่ฉันกำลังมองหาไลบรารี JS ใด ๆ ที่สามารถทำได้สำหรับอักขระการหลบหนีทั้งหมด
Srikant

1
ทำไมคุณต้องหนีขึ้นบรรทัดใหม่ภายใน JSON ค่าเหล่านี้ถูกถอดรหัสอย่างไรเมื่อใช้งานเนื่องจากวิธีแก้ไขที่เหมาะสมคือการใช้ฟังก์ชันการเข้ารหัสที่เกี่ยวข้อง
zzzzBov

ฉันใช้เวลา 6 ชั่วโมงในการลองทุกสิ่งที่มีการเปลี่ยนแปลงมากมายเพื่อค้นพบสแลชเพิ่มเติมเล็ก ๆ ที่จะทำให้มันทำงานเหมือนเวทมนตร์สิ่งที่ฉันคิดว่ามันยากใช้เวลา 5 นาที ... สิ่งที่ฉันคิดว่าเป็นไปไม่ได้ .omg
Muhammad Umer

1
เมื่อคุณใช้ Ajax-calls กับฝั่งเซิร์ฟเวอร์ php-db-saving เพียงใช้ php-function addlashes () เพื่อแปลง ด้วยโซลูชันนี้คุณมีที่เดียวสำหรับการแปลงและสะอาดกว่า javascript-replace บรรทัด
Marcel Ennix

ดูคำตอบและคำตอบที่เกี่ยวข้องได้ที่http://stackoverflow.com/questions/30366324/unescape-special-characters-in-ajax-response-data
kofifus

คำตอบ:


135

ใช้ JSON ของคุณและ.stringify()มัน จากนั้นใช้.replace()วิธีการและแทนที่เกิดขึ้นทั้งหมดด้วย\n\\n

แก้ไข:

เท่าที่ฉันรู้ไม่มีไลบรารี JS ที่รู้จักกันดีสำหรับการหลบหนีอักขระพิเศษทั้งหมดในสตริง แต่คุณสามารถโยง.replace()วิธีและแทนที่อักขระพิเศษทั้งหมดเช่นนี้:

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. 

แต่มันน่ารังเกียจใช่มั้ย ใส่ความงามของฟังก์ชั่นในการที่จะช่วยให้คุณที่จะทำลายรหัสเป็นชิ้นและให้การไหลหลักของการทำความสะอาดสคริปต์ของคุณและเป็นอิสระจาก 8 ล่ามโซ่.replace()สาย งั้นลองใส่ฟังก์ชั่นนั้นเป็นฟังก์ชั่นที่เรียกว่า, escapeSpecialChars(). ไปข้างหน้าแล้วแนบมันเข้าprototype chainกับStringวัตถุเพื่อที่เราจะสามารถโทรหาescapeSpecialChars()วัตถุ String ได้โดยตรง

ชอบมาก

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

เมื่อเราได้กำหนดฟังก์ชั่นนั้นแล้วเนื้อหาหลักของโค้ดของเราก็เรียบง่ายอย่างนี้:

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

3
ขอบคุณอเล็กซ์ ฉันต้องทำสิ่งนี้กับตัวละครหนีทั้งหมดใช่มั้ย มีห้องสมุด JS ที่จะทำเช่นนี้?
Srikant

2
นี่คือฟังก์ชันที่แน่นอนซึ่งแก้ไขปัญหาของฉัน String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\\") แทนที่ (/ \ n / g, "\\ n") แทนที่ (/ \ r / g, "\\ r") แทนที่ (/ \ t / g, "\\ t") แทนที่ (/ \ f / g, "\\ f") แทนที่ (/ "/ g" \\\ "") แทนที่ (/ '/ g "\\\') แทนที่ (/ \ & / g, "\\ &"); }
Srikant

10
ตามที่ระบุไว้ในคำตอบโดยผู้ใช้ 667073 มีข้อผิดพลาดเล็กน้อยในการแก้ปัญหานี้ ดู json.org - & & ' ต้องไม่หนีไป
Alexander Klimetschek

5
ฉันต้องลงคะแนนนี้เนื่องจากการแสดงออกปกติดูเหมือนจะผิด ฉันพยายามใช้ แต่ต้องแก้ไขนิพจน์ทั่วไปโดยการลบเครื่องหมายทับหนึ่งอันตัวอย่างเช่น: / \\ n / g ควรเป็น / \ n / g ดูที่ "ตัวละครที่ไม่สามารถพิมพ์ได้" ที่ลิงค์นี้สำหรับรายละเอียด - ข้อมูล RegExp
b01

1
แล้วตัวมันเองล่ะ? ควรที่จะหลบหนีด้วย?
arash moeen

65

ตามที่แนะนำต่อผู้ใช้ 667073 ยกเว้นการจัดเรียงการเปลี่ยนแบ็กสแลชใหม่ก่อนและแก้ไขการแทนที่คำพูด

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
คุณไม่ต้องทำสิ่งเหล่านี้ทั้งหมด เฉพาะแบ็กสแลช, ขึ้นบรรทัดใหม่, ตัวป้อนบรรทัดและทั้งสองราคา และก็ขาดหายไป: อ้างเดี่ยวและLine separator \u2028 Paragraph separator \u2029Ref: es5.github.io/#x7.3
Ariel

1
ดี แต่ทำไมวงเล็บเหลี่ยมถึงจำเป็นและไม่ใช่: escape = function (str) {return str .replace (/ \\ / g, '\\\\') .replace (/ \ "/ g, '\\\ "') .replace (/ \ // g,' \\ / ') .replace (/ \ b / g,' \\ b ') .replace (/ \ f / g,' \\ f ') .replace (/ \ n / g, '\\ n'). แทนที่ (/ \ r / g, '\\ r'). แทนที่ (/ \ t / g, '\\ t'); };
โยฮันน์ Echavarria

3
สมบูรณ์ คำตอบที่ยอมรับได้ (เหนือคำตอบนี้) ก็ไม่ได้ผล ใช้ nodeJS
Yossi Shasho

ฉันได้รับข้อผิดพลาดนี้:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros

32

เช่นเดียวกับคุณฉันได้ดูข้อคิดเห็นและโพสต์หลายรายการเพื่อแทนที่อักขระพิเศษใน JSON ของฉันซึ่งมีวัตถุ html ข้างในนั้น

วัตถุของฉันคือการลบอักขระพิเศษในวัตถุ JSON และยังแสดง html ที่อยู่ภายในวัตถุ json

นี่คือสิ่งที่ฉันทำและหวังว่าจะใช้งานได้ง่ายมาก

ครั้งแรกที่ฉันทำ JSON.string วัตถุ json ของฉันและ JSON.parse ผลลัพธ์

สำหรับเช่น:

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

และมันแก้ปัญหาของฉันและใช้งาน Javascript แบบเพียว


4
นี่เป็นวิธีที่จะไปแน่นอน
Oz Lodriguez

1
นี่เป็นวิธีที่จะไปอย่างแน่นอน!
MartianE

1
สิ่งนี้จะทำลายวัตถุที่ซับซ้อนและมีขนาดใหญ่อย่างแน่นอนโดยมีstackoverflowข้อผิดพลาด
AaA

1
ลองJSON.parse(JSON.stringify($("body")))ในไฟล์ html ที่มีเนื้อหาและบางตาราง $ ("body") เป็นวัตถุจาวาสคริปต์ แต่ stringify จะไม่สามารถแยกวิเคราะห์ได้
AaA

ฉันจะตรวจสอบข้อความค้นหาของคุณและย้อนกลับ
Balasubramani M

24

ฉันกลัวที่จะพูดว่าคำตอบที่ Alex ให้ไว้นั้นค่อนข้างไม่ถูกต้อง

  • ตัวละครบางตัวอเล็กซ์พยายามหลบหนีไม่จำเป็นต้องหลบหนีเลย (เช่น & และ ');
  • \ b ไม่ได้อยู่ที่อักขระ backspace ทั้งหมด แต่เป็นการจับคู่ขอบเขตของคำ
  • อักขระที่ต้องใช้เพื่อหลบหนีจะไม่ได้รับการจัดการ

ฟังก์ชั่นนี้

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

ดูเหมือนจะเป็นการประมาณที่ดีกว่า


5
จริง ๆ แล้วคุณควรเปลี่ยนคำสั่งเพื่อแทนที่แบ็กสแลชก่อนที่จะใส่เครื่องหมายอัญประกาศคู่มิฉะนั้นคุณจะต้องลงท้ายด้วย \\\\ "นอกจากนี้บรรทัดคำพูดควรเป็น. แทนที่ (/ [\"] / g, '\\\ "')
Ryan

10

อัพเดตเล็กน้อยสำหรับเครื่องหมายคำพูดเดี่ยว

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

นี่คือโพสต์เก่า แต่มันอาจจะเป็นประโยชน์สำหรับผู้ที่ใช้ angular.fromJson และ JSON.stringify escape () เลิกใช้แล้ว ใช้สิ่งนี้แทน

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 หมดแล้วสำหรับคุณ - ฉันอยากรู้ว่าทำไมไม่ใช้เพียงแค่นั้น git.io/vglq7
Ben Davis

5

นอกจากนี้ยังมีพารามิเตอร์ที่สองใน JSON.stringify ดังนั้นการแก้ปัญหาที่สง่างามมากขึ้นจะเป็น:

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

นี่เป็นคำถามเก่า แต่วิธีแก้ปัญหาใช้ไม่ได้ผลกับฉันเพราะมันไม่ได้แก้ปัญหาทุกกรณี ในที่สุดฉันก็พบคำตอบที่ทำงานได้ที่นี่

ฉันจะโพสต์โซลูชันรวมของฉันโดยใช้ทั้ง escape และ encode uri component:

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

อาจลบเครื่องหมายคำพูดคู่รอบ ๆ สตริงด้วยหรือไม่ escape = (string) -> JSON.stringify(string)[1...-1]
Radek


3

ใช้json_encode ()ถ้า lang scripting ฝั่งเซิร์ฟเวอร์ของคุณคือ PHP, json_encode()หนีขึ้นบรรทัดใหม่ & โทเค็นที่ไม่คาดคิดอื่น ๆ สำหรับคุณ (ถ้าไม่ได้ใช้ PHP มองหาฟังก์ชั่นที่คล้ายกันสำหรับภาษาสคริปต์ของคุณ)

จากนั้นใช้$.parseJSON()ใน JavaScript ของคุณเสร็จแล้ว!


หากการส่งข้อมูลจาก PHP ไปยังจาวาสคริปต์เป็นสตริง JSON ให้ตรวจสอบคำตอบนี้ - การหลบหนีสองครั้งช่วยให้ฉันผ่าน JSON.parse และแปลงสตริง json เป็นวัตถุ <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> php JSON.parse double encode
Vladimir Vukanac

2

ฉันได้รับสถานการณ์เดียวกันในการโทร Ajax ครั้งหนึ่งของฉันซึ่งJSONเกิดข้อผิดพลาดเนื่องจากการขึ้นบรรทัดใหม่ในฟิลด์ Textarea วิธีแก้ปัญหาของที่นี่ไม่ได้ผลสำหรับฉัน ดังนั้นฉันจึงใช้.escapeฟังก์ชั่นของ Javascript และใช้งานได้ดี จากนั้นเพื่อดึงค่าจากJSONฉันเพียงแค่ไม่ใช้ Escape .unescapeใช้


ใช้ Ajax call ฉันชอบใช้ php-function newStr = addlashes (str) จากนั้นบันทึกเป็น db ดังนั้นฉันไม่ต้องแปลงที่ javascript- (ลูกค้า) - ด้าน ด้วยโซลูชันนี้คุณต้องการเพียงที่เดียวเท่านั้นในการแปลงสแลช ฉันมีความสุขมากกับการแก้ปัญหานี้
Marcel Ennix

2

ฉันใช้ built in ในjQuery.serialize ()เพื่อแยกค่าจาก textarea เพื่อ urlencode อินพุต ส่วนที่เป็นมือโปรคือคุณไม่ต้องทำการค้นหาแทนที่ char พิเศษทุกตัวด้วยตัวคุณเองและฉันก็ยังคงบรรทัดใหม่และ html ที่หนีออกมา สำหรับซีเรียลไลซ์สำหรับการทำงานดูเหมือนว่าฟิลด์อินพุตจำเป็นต้องมีแอ็ตทริบิวต์ name และมันยังเพิ่มแอ็ตทริบิวต์เดียวกันให้กับสตริงที่ใช้ Escape ซึ่งต้องถูกแทนที่ อาจไม่ใช่สิ่งที่คุณกำลังมองหา แต่มันก็ได้ผลสำหรับฉัน

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

1

เมื่อใช้ Ajax รูปแบบใด ๆ เอกสารรายละเอียดสำหรับรูปแบบของการตอบสนองที่ได้รับจากเซิร์ฟเวอร์ CGI ดูเหมือนว่าจะไม่เพียงพอบนเว็บ บางรายการในที่นี้ชี้ให้เห็นว่าบรรทัดใหม่ในข้อความที่ส่งคืนหรือข้อมูล json ต้องถูกหลีกเลี่ยงเพื่อป้องกันการวนซ้ำไม่สิ้นสุด (แฮงค์) ในการแปลง JSON (อาจสร้างขึ้นโดยการโยนข้อยกเว้นที่ไม่ถูกตรวจจับ) ไม่ว่าจะกระทำโดยอัตโนมัติ โทร

ในแต่ละกรณีที่โปรแกรมเมอร์โพสต์ปัญหานี้จะมีวิธีแก้ปัญหาไม่เพียงพอ (ส่วนใหญ่มักจะแทนที่ \ n ด้วย \\ n ทางด้านการส่ง) และเรื่องจะถูกทิ้ง ความไม่เพียงพอของข้อมูลเหล่านี้จะถูกเปิดเผยเมื่อส่งผ่านค่าสตริงที่ฝังลำดับการควบคุมการหนีโดยไม่ตั้งใจเช่นชื่อพา ธ ของ Windows ตัวอย่างคือ "C: \ Chris \ Roberts.php" ซึ่งมีอักขระควบคุม ^ c และ ^ r ซึ่งสามารถทำให้การแปลง JSON ของสตริง {"ไฟล์": "C: \ Chris \ Roberts.php"} เป็น วนซ้ำตลอดไป วิธีหนึ่งในการสร้างค่าดังกล่าวคือการพยายามส่งคำเตือน PHP และข้อความแสดงข้อผิดพลาดจากเซิร์ฟเวอร์ไปยังไคลเอนต์ซึ่งเป็นแนวคิดที่สมเหตุสมผล

ตามคำนิยาม Ajax ใช้การเชื่อมต่อ HTTP ที่อยู่เบื้องหลัง การเชื่อมต่อดังกล่าวส่งผ่านข้อมูลโดยใช้ GET และ POST ซึ่งทั้งสองอย่างนั้นต้องการการเข้ารหัสข้อมูลที่ส่งเพื่อหลีกเลี่ยงไวยากรณ์ที่ไม่ถูกต้องรวมถึงอักขระควบคุม

สิ่งนี้ให้คำแนะนำเพียงพอที่จะสร้างสิ่งที่ดูเหมือนว่าจะเป็นทางออก (ต้องมีการทดสอบเพิ่มเติม): ใช้ rawurlencode บนด้าน PHP (ส่ง) เพื่อเข้ารหัสข้อมูลและ unescape บนฝั่ง Javascript (ที่ได้รับ) เพื่อถอดรหัสข้อมูล ในบางกรณีคุณจะใช้สิ่งเหล่านี้กับสตริงข้อความทั้งหมดในกรณีอื่น ๆ คุณจะใช้กับค่าภายใน JSON เท่านั้น

หากความคิดนี้ถูกต้องตัวอย่างที่เรียบง่ายสามารถสร้างขึ้นเพื่อช่วยโปรแกรมเมอร์ในทุกระดับแก้ปัญหานี้ได้ในทันที


0

ดูเหมือนว่านี่เป็นโพสต์โบราณจริงๆ :-) แต่พวกที่ดีที่สุดที่ฉันมีเพื่อให้เป็น 100% ว่ามันทำงานได้โดยไม่ต้องใช้รหัสที่ซับซ้อนคือการใช้ทั้งการเข้ารหัส / ถอดรหัสไปยัง base64 เหล่านี้คือ atob () และ btoa () เท่าที่ผ่านมาวิธีที่ง่ายและดีที่สุดไม่ต้องกังวลหากคุณพลาดตัวละครใด ๆ ที่ต้องหลบหนี

จอร์จ


ตั้งแต่ฉันมาด้วยวิธีเดียวกัน ฉันสงสัยว่ามีใครบางคนสามารถอธิบายวิธีการแก้ปัญหานี้และแม้ว่าจะมีบางประการที่ซ่อนอยู่ ขอบคุณ
mahish

0

หาก Googles ของคุณเชื่อมโยงไปถึงคุณที่นี่และ api ของคุณโยนข้อผิดพลาดยกเว้นว่าเครื่องหมายอัญประกาศคู่ของ JSON ของคุณจะถูกหลบหนี ( "{\"foo\": true}") สิ่งที่คุณต้องทำคือการทำให้เป็นสองเท่าเช่นJSON.stringify(JSON.stringify(bar))


-1

ใช้ encodeURIComponent () เพื่อเข้ารหัสสตริง

เช่น. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

คุณไม่จำเป็นต้องถอดรหัสเนื่องจากเว็บเซิร์ฟเวอร์ทำเช่นเดียวกันโดยอัตโนมัติ


-8

ไม่เคยใช้การแสดงออกปกติ (ฉันหมายถึงไม่เคยเลย) วิธีที่ดีที่สุดและมีประสิทธิภาพ:

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

คุณไม่สามารถพูดว่า "ไม่เคยใช้การแสดงออกปกติ (ฉันหมายถึงไม่เคยเลย)" เครื่องมือทุกอย่างให้บริการตามวัตถุประสงค์
zstate

คำตอบของคุณถูกต้องคุณเพิ่งแสดงความคิดเห็นอย่างสูงซึ่งอาจสร้างความสับสนโดยเฉพาะอย่างยิ่งสำหรับรุ่นน้อง
zstate

@ การเข้ารหัสปกติของนิพจน์นั้นไร้ประโยชน์อย่างไม่น่าเชื่อไม่ว่าจะใช้อย่างไรและเมื่อไหร่ มันจะนำไปสู่พฤติกรรมที่ไม่ได้กำหนดและเสียเวลาของ CPU
Alek Depler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.