213

I have to form a JSON string in which a value is having new line character. This has to be escaped and then posted using AJAX call. Can any one suggest a way to escape the string with JavaScript. I am not using jQuery.

Brett DeWoody
  • 59,771
  • 29
  • 135
  • 184
Srikant
  • 2,161
  • 2
  • 13
  • 5
  • 3
    I tried escaping the new line character \n to \\n. It is working fine. But i am looking for any JS library which can do this for all the escape characters. – Srikant Nov 23 '10 at 06:40
  • 1
    Why do you need to escape the newlines within the JSON? How are these values being decoded when they're used, because the appropriate solution is to use the related encoding function. – zzzzBov Oct 04 '13 at 20:41
  • i spent 6 hours trying all kinds of things with tons of variations only to discover a tiny additional slash would make it all work like magic the things i thought were hard took like 5 mins...the thing i thought was given became the impossible..omg – Muhammad Umer Mar 02 '14 at 17:19
  • 1
    When you use Ajax-calls with Server-Side php-db-saving, just use the php-function addslashes() to convert it. With this solution you only have one place to convert and its cleaner than the javascript-replace lines. – Marcel Ennix Feb 12 '15 at 16:21
  • 1
    See relevant answer and solution at [http://stackoverflow.com/questions/30366324/unescape-special-characters-in-ajax-response-data](http://stackoverflow.com/questions/30366324/unescape-special-characters-in-ajax-response-data) – kofifus Feb 27 '17 at 03:52

17 Answers17

157

Take your JSON and .stringify() it. Then use the .replace() method and replace all occurrences of \n with \\n.

EDIT:

As far as I know of, there are no well-known JS libraries for escaping all special characters in a string. But, you could chain the .replace() method and replace all of the special characters like this:

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. 

But that's pretty nasty, isn't it? Enter the beauty of functions, in that they allow you to break code into pieces and keep the main flow of your script clean, and free of 8 chained .replace() calls. So let's put that functionality into a function called, escapeSpecialChars(). Let's go ahead and attach it to the prototype chain of the String object, so we can call escapeSpecialChars() directly on String objects.

Like so:

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

Once we have defined that function, the main body of our code is as simple as this:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server
avngr
  • 323
  • 3
  • 12
Alex
  • 64,178
  • 48
  • 151
  • 180
  • 3
    Thanks alex. I have to do this for all the escape characters right? Is there is any JS library to do this? – Srikant Nov 23 '10 at 06:44
  • This worked with little modification. var myEscapedJSONString = myJSONString.replace(/\n/g, "\\n"); This has replaced all the occurances of '\n'. Can you suggest a JS library to do this. Or else i have to handle all the Escape characters. Thanks in advance. – Srikant Nov 23 '10 at 06:50
  • 5
    This is the exact function which solved my 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 Nov 23 '10 at 09:32
  • 11
    As noted in the answer by user667073, there are a few errors in this solution. See json.org - & and ' *must not* be escaped. – Alexander Klimetschek Nov 15 '11 at 22:07
  • why call replace so many times? wouldnt something like .replace(/[\n\r\t\b\f\\]/g, function(s){ return "\\" + s }) work? – lordvlad Dec 13 '12 at 16:19
  • 5
    I had to down-vote this since the regular expressions seem to be wrong. I tried to use it, but had to fix the regular expressions by removing one of the slashes, for example: /\\n/g should be /\n/g. See "Non-Printable Characters" at this link for details - [RegExp Info](http://www.regular-expressions.info/characters.html) – b01 Mar 01 '13 at 16:24
  • How can you suggest a method to encode a string (which is what escaping a string actually is) when you don't even know how the string is to be decoded? These sorts of "escape" functions are the wrong solution. – zzzzBov Oct 04 '13 at 20:39
  • 1
    what about \ itself? should that also be escaped ? – arash moeen Sep 15 '14 at 07:53
  • Sorry had to downvote because Ryan's answer works and yours doesnt. please update for my upvote – fotoflo Jul 18 '15 at 03:36
  • `stringify` already does all the escaping for you. Why would you need to do it twice? https://git.io/vglq7 – Ben Davis Feb 06 '16 at 15:36
  • 2
    In order to also escape backslashes, add `.replace(/\\/g, "\\\\")`. It's kind of sad that we have to do it this way and there isn't a function provided by js. – jakob.j Jan 14 '19 at 10:17
  • Had to downvote, since this won't work on say _"Hello \ not hello"_. `JSON.stringify` will lose the backslash \ completely. – lofihelsinki Nov 25 '20 at 09:15
  • Wow! No comment on "Enter the beauty of functions" yet? Was that part really necessary? @Alex – tishma Nov 13 '22 at 13:56
85

As per user667073 suggested, except reordering the backslash replacement first, and fixing the quote replacement

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
  • 5,416
  • 1
  • 39
  • 36
  • 4
    You don't have to do all of these. Only backslash, newline, linefeed, and the two quotes. And it's missing: Single quote, `Line separator` `\u2028` and `Paragraph separator` `\u2029`. Ref: http://es5.github.io/#x7.3 – Ariel May 12 '13 at 20:43
  • 2
    Nice, but why are the square brackets necessary and not: 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 Nov 27 '15 at 20:27
  • 5
    perfect. the accepted answer (above this one) simply doesn't work. using nodeJS. – Yossi Shasho Sep 04 '16 at 09:34
  • I get this error: `Uncaught SyntaxError: Unexpected token \ in JSON at position 2` – Pathros Feb 07 '17 at 15:42
40

Like you, I have been looking into several comments and post to replace special escape characters in my JSON which contains html object inside that.

My object is to remove the special characters in JSON object and also render the html which is inside the json object.

Here is what I did and hope its very simple to use.

First I did JSON.stringify my json object and JSON.parse the result.

For eg:

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

And it solves my problem and done using Pure Javascript.

Balasubramani M
  • 7,742
  • 2
  • 45
  • 47
28

I'm afraid to say that answer given by Alex is rather incorrect, to put it mildly:

  • Some characters Alex tries to escape are not required to be escaped at all (like & and ');
  • \b is not at all the backspace character but rather a word boundary match
  • Characters required to be escaped are not handled.

This function

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

appears to be a better approximation.

wh81752
  • 869
  • 9
  • 16
  • 5
    actually you should change the order to replace the backslashes before the double quotes, or else you'll end up with \\\\". Also the quote line should be .replace(/[\"]/g, '\\\"') – Ryan Feb 01 '12 at 04:06
12

A small update for single quotes

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);
Kjartan
  • 18,591
  • 15
  • 71
  • 96
Akash Dhawale
  • 121
  • 1
  • 2
8

this is an old post. but it may still be helpful for those using angular.fromJson, and JSON.stringify. escape() is deprecated. use this instead,

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
  • 640
  • 5
  • 15
6

There is also second parameter on JSON.stringify. So, more elegant solution would be:

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

This is an old question but the solution did not work well for me as it did not solve all cases. I finally found an answer that did the job here

I will post my combined solution of both using escape and 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);
}
Community
  • 1
  • 1
Mitzi
  • 2,652
  • 1
  • 20
  • 15
  • 1
    Maybe remove the double quotes around the string afterwards too? ```escape = (string) -> JSON.stringify(string)[1...-1]``` – Radek Oct 01 '13 at 15:20
4

RegExp single line, use this function:

function escapeJSON(string) {
    return string.replace(/[\n"\&\r\t\b\f]/g, '\\$&');
}
Asalan
  • 85
  • 2
  • 11
3

I got same situation in one of my Ajax calls, where JSON was throwing an error due to the newline in the Textarea field. The solution given here didn't worked for me. So i used Javascript's .escape function and it worked fine. Then to retrieve the value from JSON, I just unescaped using .unescape.

ashley
  • 2,749
  • 5
  • 26
  • 38
Anubhav Trivedi
  • 1,130
  • 1
  • 12
  • 19
  • Using Ajax calls, i prefer to use php-function newStr = addslashes(str), then save to db. So i dont have to convert at javascript-(client)-side. With this solution you need only one place to convert the slashes. Im very happy with this solution. – Marcel Ennix Feb 12 '15 at 16:17
3

Use json_encode() if your server side scripting lang is PHP, json_encode() escapes the newline & other unexpected tokens for you (if not using PHP look for similar function for your scripting language)

then use $.parseJSON() in your JavaScript, done!

ata
  • 3,398
  • 5
  • 20
  • 31
avngr
  • 323
  • 3
  • 12
  • If passing data from php to javascript as JSON string, check this answer - double escaping, helped me to pass JSON.parse and convert json string to object. `` [php JSON.parse double encode](http://stackoverflow.com/a/1048555/2873481) – Vladimir Vukanac Nov 19 '14 at 10:08
3

It's better to use JSON.parse(yourUnescapedJson);

Unheilig
  • 16,196
  • 193
  • 68
  • 98
Mohit Vachhani
  • 108
  • 1
  • 2
  • 5
3

EDIT: Check if the api you’re interacting with is set to Content-Type: application/json, &/or if your client http library is both stringify-ing and parsing the http request body behind the scenes. My client library was generated by swagger, and was the reason I needed to apply these hacks, as the client library was stringifying my pre-stringified body (body: “jsonString”, instead of body: { ...normal payload }). All I had to do was change the api to Content-Type: text/plain, which removed the JSON stringify/parsing on that route, and then none of these hacks were needed. You can also change only the "consumes" or "produces" portion of the api, see here.

ORIGINAL: If your Googles keep landing you here and your api throws errors unless your JSON double quotes are escaped ("{\"foo\": true}"), all you need to do is stringify twice e.g. JSON.stringify(JSON.stringify(bar))

Andrew
  • 1,406
  • 1
  • 15
  • 23
  • Thanks @jasonco, but not really. This question is a decade old! Check my edit, it may help you. – Andrew Dec 19 '20 at 00:56
  • hi @Andrew, thanks! still your original answer helped me, at least for what I was doing, which was also a bit hacky :) – jasonco Dec 21 '20 at 20:32
2

I used the built in jQuery.serialize() to extract the value from a textarea to urlencode the input. The pro part is that you don't have to search replace every special char on your own and i also keep the newlines and escapes html. For serialize to work it seems the input field needs to have a name attribute though and it also adds same attribute to the escaped string which needs to be replaced away. Might not be what you are looking for but it works for me.

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

When using any form of Ajax, detailed documentation for the format of responses received from the CGI server seems to be lacking on the Web. Some entries here point out that newlines in returned text or json data must be escaped to prevent infinite loops (hangs) in JSON conversion (possibly created by throwing an uncaught exception), whether done automatically by jQuery or manually using Javascript system or library JSON parsing calls.

In each case where programmers post this problem, inadequate solutions are presented (most often replacing \n by \\n on the sending side) and the matter is dropped. Their inadequacy is revealed when passing string values that accidentally embed control escape sequences, such as Windows pathnames. An example is "C:\Chris\Roberts.php", which contains the control characters ^c and ^r, which can cause JSON conversion of the string {"file":"C:\Chris\Roberts.php"} to loop forever. One way of generating such values is deliberately to attempt to pass PHP warning and error messages from server to client, a reasonable idea.

By definition, Ajax uses HTTP connections behind the scenes. Such connections pass data using GET and POST, both of which require encoding sent data to avoid incorrect syntax, including control characters.

This gives enough of a hint to construct what seems to be a solution (it needs more testing): to use rawurlencode on the PHP (sending) side to encode the data, and unescape on the Javascript (receiving) side to decode the data. In some cases, you will apply these to entire text strings, in other cases you will apply them only to values inside JSON.

If this idea turns out to be correct, simple examples can be constructed to help programmers at all levels solve this problem once and for all.

David Spector
  • 1,520
  • 15
  • 21
1

Looks like this is an ancient post really :-) But guys, the best workaround I have for this, to be 100% that it works without complicated code, is to use both functions of encoding/decoding to base64. These are atob() and btoa(). By far the easiest and best way, no need to worry if you missed any characters to be escaped.

George

OrangeG
  • 169
  • 7
  • Since I came up with the same solution. I wonder if someone could clarify this solution and wheter there are some hidden caveats. Thanks. – mahish Jul 19 '18 at 16:05
  • @mahish a little late to the party, but you have to worry about characters outside the 'Latin1' range like ✓ à la mode You can encodeURIComponent and you won't get the JavaScript error, but you'll lose the higher numbered unicode characters when you call revert the data back. So to encode: `var b = btoa(encodeURIComponent(q).replace(/%([0-9A-F]{2})/g, function (m, p1) { return String.fromCharCode('0x' + p1) }))` To decode: `var u = decodeURIComponent(escape(atob(b)))` Most of this was from stack overflow answers from various questions. – Charles Byrne Oct 07 '21 at 13:22
-1

Use encodeURIComponent() to encode the string.

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

You don't need to decode it since the web server automatically do the same.

Sanju Kaniyamattam
  • 501
  • 1
  • 4
  • 14