Làm cách nào để thoát chuỗi JSON chứa các ký tự dòng mới bằng JavaScript?


166

Tôi phải tạo một chuỗi JSON trong đó một giá trị có ký tự dòng mới. Điều này phải được thoát và sau đó được đăng bằng cách sử dụng cuộc gọi AJAX. Có ai có thể đề xuất một cách để thoát chuỗi bằng JavaScript không. Tôi không sử dụng jQuery.


1
Tôi đã thử thoát ký tự dòng mới \ n đến \\ n. Nó đang hoạt động tốt. Nhưng tôi đang tìm kiếm bất kỳ thư viện JS nào có thể làm điều này cho tất cả các ký tự thoát.
Srikant

1
Tại sao bạn cần thoát các dòng mới trong JSON? Làm thế nào các giá trị này được giải mã khi chúng được sử dụng, bởi vì giải pháp thích hợp là sử dụng chức năng mã hóa liên quan.
zzzzBov

tôi đã dành 6 giờ để thử tất cả mọi thứ với hàng tấn biến thể chỉ để khám phá ra một nhát chém bổ sung nhỏ sẽ khiến mọi thứ hoạt động như ma thuật, những điều tôi nghĩ là khó khăn trong 5 phút ... điều tôi nghĩ là không thể. .omg
Muhammad Umer

1
Khi bạn sử dụng các cuộc gọi Ajax với lưu trữ php-db phía máy chủ, chỉ cần sử dụng hàm thêm hàm php () để chuyển đổi nó. Với giải pháp này, bạn chỉ có một nơi để chuyển đổi và nó sạch hơn các dòng thay thế javascript.
Marcel Ennix

Xem câu trả lời và giải pháp có liên quan tại http://stackoverflow.com/questions/30366324/unescape-special-char
character

Câu trả lời:


134

Lấy JSON của bạn và .stringify()nó. Sau đó sử dụng .replace()phương pháp và thay thế tất cả các lần xuất hiện \nbằng \\n.

BIÊN TẬP:

Theo như tôi biết, không có thư viện JS nổi tiếng nào để thoát tất cả các ký tự đặc biệt trong một chuỗi. Nhưng, bạn có thể xâu chuỗi .replace()phương thức và thay thế tất cả các ký tự đặc biệt như thế này:

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. 

Nhưng điều đó thật khó chịu phải không? Nhập vào vẻ đẹp của các hàm, trong đó chúng cho phép bạn chia mã thành nhiều phần và giữ cho luồng chính của tập lệnh của bạn sạch sẽ và không có 8 .replace()cuộc gọi bị xiềng xích . Vì vậy, hãy đặt chức năng đó vào một chức năng được gọi là escapeSpecialChars(). Chúng ta hãy đi trước và đính kèm nó vào prototype chaincác Stringđối tượng, vì vậy chúng tôi có thể gọi escapeSpecialChars()trực tiếp trên chuỗi các đối tượng.

Thích như vậy:

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

Khi chúng ta đã xác định hàm đó, phần chính của mã của chúng ta đơn giản như sau:

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

3
Cảm ơn alex. Tôi phải làm điều này cho tất cả các nhân vật thoát phải không? Có thư viện JS nào để làm việc này không?
Srikant

2
Đây là hàm chính xác đã giải quyết vấn đề của tôi String.prototype.escapeecialChars = function () {return this.replace (/ \\ / g, "\\\\"). thay thế (/ \ n / g, "\\ n"). thay thế (/ \ r / g, "\\ r"). thay thế (/ \ t / g, "\\ t"). thay thế (/ \ f / g, "\\ f"). thay thế (/ "/ g," \\\ ""). thay thế (/ '/ g, "\\\'"). thay thế (/ \ & / g, "\\ &"); }
Srikant

10
Như đã lưu ý trong câu trả lời của user667073, có một vài lỗi trong giải pháp này. Xem json.org - & và ' không được thoát.
Alexander Klimetschek

5
Tôi đã phải bỏ phiếu này vì các biểu thức thông thường dường như là sai. Tôi đã cố gắng sử dụng nó, nhưng phải sửa các biểu thức thông thường bằng cách xóa một trong các dấu gạch chéo, ví dụ: / \\ n / g nên là / \ n / g. Xem "Ký tự không in được" tại liên kết này để biết chi tiết - Thông tin RegExp
b01

1
Còn bản thân nó thì sao? điều đó cũng nên được trốn thoát?
arash moeen

65

Theo người dùng667073 đã đề xuất, ngoại trừ sắp xếp lại thay thế dấu gạch chéo ngược trước và sửa lỗi thay thế báo giá

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
Bạn không phải làm tất cả những điều này. Chỉ dấu gạch chéo ngược, dòng mới, nguồn cấp dữ liệu và hai dấu ngoặc kép. Và nó còn thiếu: Trích dẫn duy nhất, Line separator \u2028Paragraph separator \u2029. Tham chiếu: es5.github.io/#x7.3
Ariel

1
Đẹp, nhưng tại sao các dấu ngoặc vuông cần thiết và không: esc = 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
hoàn hảo. câu trả lời được chấp nhận (trên câu hỏi này) đơn giản là không hoạt động. sử dụng nútJS.
Yossi Shasho

Tôi nhận được lỗi này:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros

31

Giống như bạn, tôi đã xem xét một số bình luận và bài đăng để thay thế các ký tự thoát đặc biệt trong JSON của tôi có chứa đối tượng html bên trong đó.

Đối tượng của tôi là loại bỏ các ký tự đặc biệt trong đối tượng JSON và cũng hiển thị html nằm trong đối tượng json.

Đây là những gì tôi đã làm và hy vọng nó rất đơn giản để sử dụng.

Đầu tiên tôi đã thực hiện JSON.opesify đối tượng json của tôi và JSON.parse kết quả.

Ví dụ:

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

Và nó giải quyết vấn đề của tôi và thực hiện bằng Pure Javascript.


4
Đây chắc chắn là con đường để đi
Oz Lodriguez

1
Điều này chắc chắn là con đường để đi!
Sao Hỏa

1
Điều này chắc chắn sẽ phá vỡ các đối tượng phức tạp và lớn có stackoverflowlỗi
AaA

1
thử JSON.parse(JSON.stringify($("body")))trong một tệp html có phần thân và một vài bảng. $ ("body") là một đối tượng javascript nhưng Stringify sẽ không phân tích cú pháp.
AaA

Tôi sẽ kiểm tra truy vấn của bạn và hoàn nguyên.
Balasubramani M

24

Tôi sợ nói rằng câu trả lời được đưa ra bởi Alex là không chính xác, để nói một cách nhẹ nhàng:

  • Một số nhân vật Alex cố gắng trốn thoát hoàn toàn không cần phải trốn thoát (như & và ');
  • \ b hoàn toàn không phải là ký tự backspace mà là một kết hợp ranh giới từ
  • Nhân vật cần phải thoát không được xử lý.

Chức năng này

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

dường như là một xấp xỉ tốt hơn.


5
trên thực tế, bạn nên thay đổi thứ tự để thay thế dấu gạch chéo ngược trước dấu ngoặc kép, nếu không bạn sẽ kết thúc bằng \ \ ". Ngoài ra, dòng trích dẫn phải là .replace (/ [\"] / g, '\\\ "')
Ryan

10

Một bản cập nhật nhỏ cho dấu ngoặc đơn

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

đây là một bài viết cũ nhưng nó vẫn có thể hữu ích cho những người sử dụng angular.fromJson và JSON.opesify. thoát () bị phản đối sử dụng cái này thay thế

var uri_enc = encodeURIComponent(uri); //before you post the contents
var uri_dec = decodeURIComponent(uri_enc); //before you display/use the contents.

tham khảo http://www.w3schools.com/jsref/jsref_decodeuricomponent.asp


xâu chuỗi tất cả các lối thoát cho bạn - Tôi tò mò tại sao không sử dụng nó? git.io/vglq7
Ben Davis

5

Ngoài ra còn có tham số thứ hai trên JSON.opesify. Vì vậy, giải pháp thanh lịch hơn sẽ là:

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

Đây là một câu hỏi cũ nhưng giải pháp không hiệu quả với tôi vì nó không giải quyết được tất cả các trường hợp. Cuối cùng tôi đã tìm thấy một câu trả lời đã làm công việc ở đây

Tôi sẽ đăng giải pháp kết hợp cả hai bằng cách sử dụng thành phần thoát và mã hóa 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);
}

Có thể loại bỏ các dấu ngoặc kép xung quanh chuỗi sau đó? escape = (string) -> JSON.stringify(string)[1...-1]
Radek


3

Sử dụng json_encode () nếu lang kịch bản phía máy chủ của bạn là PHP, json_encode() thoát khỏi dòng mới và các mã thông báo bất ngờ khác cho bạn (nếu không sử dụng PHP, hãy tìm chức năng tương tự cho ngôn ngữ kịch bản lệnh của bạn)

sau đó sử dụng $.parseJSON()JavaScript của bạn!


Nếu chuyển dữ liệu từ php sang javascript dưới dạng chuỗi JSON, hãy kiểm tra câu trả lời này - thoát kép, giúp tôi chuyển JSON.parse và chuyển chuỗi json thành đối tượng. <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> Mã hóa kép php JSON.parse
Vladimir Vukanac

2

Tôi đã gặp tình huống tương tự trong một trong các cuộc gọi Ajax của tôi, nơi JSONđã xảy ra lỗi do dòng mới trong trường Textarea. Giải pháp đưa ra ở đây không hiệu quả với tôi. Vì vậy, tôi đã sử dụng .escapechức năng của Javascript và nó hoạt động tốt. Sau đó, để lấy giá trị từ JSON, tôi chỉ không sử dụng .unescape.


Sử dụng các cuộc gọi Ajax, tôi thích sử dụng chức năng php newStr = thêmlash (str), sau đó lưu vào db. Vì vậy, tôi không phải chuyển đổi ở phía javascript- (client). Với giải pháp này, bạn chỉ cần một nơi để chuyển đổi dấu gạch chéo. Tôi rất hài lòng với giải pháp này.
Marcel Ennix 12/2/2015

2

Tôi đã sử dụng hàm jQuery.serialize () tích hợp để trích xuất giá trị từ textarea để urlencode đầu vào. Phần chuyên nghiệp là bạn không phải tự mình tìm kiếm thay thế mọi char đặc biệt và tôi cũng giữ các dòng mới và thoát html. Để tuần tự hóa hoạt động, có vẻ như trường đầu vào cần phải có thuộc tính name và nó cũng thêm thuộc tính tương tự vào chuỗi đã thoát cần được thay thế. Có thể không phải là những gì bạn đang tìm kiếm nhưng nó làm việc cho tôi.

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

1

Khi sử dụng bất kỳ dạng Ajax nào, tài liệu chi tiết về định dạng của các phản hồi nhận được từ máy chủ CGI dường như còn thiếu trên Web. Một số mục ở đây chỉ ra rằng các dòng mới trong văn bản trả về hoặc dữ liệu json phải được thoát để tránh các vòng lặp vô hạn (treo) trong chuyển đổi JSON (có thể được tạo bằng cách ném một ngoại lệ chưa được phát hiện), cho dù được thực hiện tự động bởi jQuery hoặc sử dụng phân tích cú pháp JSON của thư viện các cuộc gọi.

Trong mỗi trường hợp các lập trình viên đăng vấn đề này, các giải pháp không đầy đủ được trình bày (thường thay thế \ n bằng \ n ở phía gửi) và vấn đề được loại bỏ. Sự không đầy đủ của chúng được tiết lộ khi truyền các giá trị chuỗi vô tình nhúng các chuỗi thoát kiểm soát, chẳng hạn như tên đường dẫn Windows. Một ví dụ là "C: \ Chris \ Roberts.php", chứa các ký tự điều khiển ^ c và ^ r, có thể gây ra chuyển đổi JSON của chuỗi {"file": "C: \ Chris \ Roberts.php"} thành vòng lặp mãi mãi. Một cách tạo ra các giá trị như vậy là cố tình truyền các thông báo lỗi và cảnh báo PHP từ máy chủ đến máy khách, một ý tưởng hợp lý.

Theo định nghĩa, Ajax sử dụng các kết nối HTTP phía sau hậu trường. Các kết nối như vậy truyền dữ liệu bằng GET và POST, cả hai đều yêu cầu mã hóa dữ liệu đã gửi để tránh cú pháp sai, bao gồm các ký tự điều khiển.

Điều này cung cấp đủ gợi ý để xây dựng giải pháp dường như là một giải pháp (cần thử nghiệm nhiều hơn): sử dụng rawurlencode ở phía PHP (gửi) để mã hóa dữ liệu và bỏ thông báo ở phía Javascript (nhận) để giải mã dữ liệu. Trong một số trường hợp, bạn sẽ áp dụng chúng cho toàn bộ chuỗi văn bản, trong các trường hợp khác, bạn sẽ chỉ áp dụng chúng cho các giá trị bên trong JSON.

Nếu ý tưởng này trở nên chính xác, các ví dụ đơn giản có thể được xây dựng để giúp các lập trình viên ở tất cả các cấp giải quyết vấn đề này một lần và mãi mãi.


0

Có vẻ như đây thực sự là một bài viết cổ xưa :-) Nhưng các bạn, cách giải quyết tốt nhất mà tôi có, là 100% nó hoạt động mà không cần mã phức tạp, là sử dụng cả hai chức năng mã hóa / giải mã thành base64. Đây là atob () và btoa (). Cho đến nay, cách dễ nhất và tốt nhất, không cần phải lo lắng nếu bạn bỏ lỡ bất kỳ nhân vật nào để trốn thoát.

George


Vì tôi đã đưa ra giải pháp tương tự. Tôi tự hỏi nếu ai đó có thể làm rõ giải pháp này và có một số cảnh báo ẩn. Cảm ơn.
mahish

0

Nếu Google của bạn tiếp tục hạ cánh bạn ở đây và api của bạn ném lỗi trừ khi dấu ngoặc kép JSON của bạn được thoát ( "{\"foo\": true}"), tất cả những gì bạn cần làm là xâu chuỗi hai lần, ví dụJSON.stringify(JSON.stringify(bar))


-1

Sử dụng encodeURIComponent () để mã hóa chuỗi.

Ví dụ. var myEscopedJSONString = encodeURIComponent (JSON.opesify (myJSON));

Bạn không cần giải mã nó vì máy chủ web sẽ tự động làm như vậy.


-8

Đừng bao giờ sử dụng các biểu thức thông thường (ý tôi là không bao giờ như vậy). Cách tốt nhất và hiệu quả:

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

Bạn không thể nói, "Đừng bao giờ sử dụng các biểu thức thông thường (ý tôi là không bao giờ như vậy)". Mỗi công cụ phục vụ mục đích của nó.
zstate

Câu trả lời của bạn là hợp lệ, bạn chỉ thể hiện nó theo một cách rất quan tâm, điều này có thể tạo ra sự nhầm lẫn, đặc biệt là đối với đàn em.
zstate

@oncode biểu thức thông thường là vô dụng đáng kinh ngạc, bất kể sử dụng chúng như thế nào và khi nào. Nó chỉ dẫn đến hành vi không xác định và lãng phí thời gian CPU.
Hà Lan Depler
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.