dinesh707
dinesh707

Reputation: 12592

How to escape special characters in building a JSON string?

Here is my string

{
    'user': {
        'name': 'abc',
        'fx': {
            'message': {
                'color': 'red'
            },
            'user': {
                'color': 'blue'
            }
        }
    },
    'timestamp': '2013-10-04T08: 10: 41+0100',
    'message': 'I'mABC..',
    'nanotime': '19993363098581330'
}    

Here the message contains single quotation mark, which is same as the quotation used in JSON. What I do is fill up a string from user inputs such as message. So, I need to escape those kind of special scenarios which breaks the code. But other than string replace, is there any way to make them escape but still allow HTML to process them back to the correct message?

Upvotes: 296

Views: 1346126

Answers (12)

Mark Amery
Mark Amery

Reputation: 155145

I'm appalled by the presence of highly-upvoted misinformation on such a highly-viewed question about a basic topic.

JSON strings cannot be quoted with single quotes. The various versions of the spec (the original by Douglas Crockford, the ECMA version, and the IETF version) all state that strings must be quoted with double quotes. This is not a theoretical issue, nor a matter of opinion as the accepted answer currently suggests; any JSON parser in the real world will error out if you try to have it parse a single-quoted string.

Crockford's and ECMA's version even display the definition of a string using a pretty picture, which should make the point unambiguously clear:

Image showing the definition of a string from the JSON spec

The pretty picture also lists all of the legitimate escape sequences within a JSON string:

  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u followed by four-hex-digits

Note that, contrary to the nonsense in some other answers here, \' is never a valid escape sequence in a JSON string. It doesn't need to be, because JSON strings are always double-quoted.

Finally, you shouldn't normally have to think about escaping characters yourself when programatically generating JSON (though of course you will when manually editing, say, a JSON-based config file). Instead, form the data structure you want to encode using whatever native map, array, string, number, boolean, and null types your language has, and then encode it to JSON with a JSON-encoding function. Such a function is probably built into whatever language you're using, like JavaScript's JSON.stringify, PHP's json_encode, or Python's json.dumps. If you're using a language that doesn't have such functionality built in, you can probably find a JSON parsing and encoding library to use. If you simply use language or library functions to convert things to and from JSON, you'll never even need to know JSON's escaping rules. This is what the misguided question asker here ought to have done.

Upvotes: 589

Damiano Falcioni
Damiano Falcioni

Reputation: 61

Here a solution that follow @Mark Amery best answer and handle the escaping of all UNICODE Control Characters generating a fully valid JSON string (+ the replacement regex is only one):

const chars = {
  "\"": "\\\"",
  "\\": "\\\\",
  "\/": "\\/",
  "\u0000": "\\u0000",
  "\u0001": "\\u0001",
  "\u0002": "\\u0002",
  "\u0003": "\\u0003",
  "\u0004": "\\u0004",
  "\u0005": "\\u0005",
  "\u0006": "\\u0006",
  "\u0007": "\\u0007",
  "\u0008": "\\u0008",
  "\u0009": "\\u0009",
  "\u000A": "\\u000A",
  "\u000B": "\\u000B",
  "\u000C": "\\u000C",
  "\u000D": "\\u000D",
  "\u000E": "\\u000E",
  "\u000F": "\\u000F",
  "\u0010": "\\u0010",
  "\u0011": "\\u0011",
  "\u0012": "\\u0012",
  "\u0013": "\\u0013",
  "\u0014": "\\u0014",
  "\u0015": "\\u0015",
  "\u0016": "\\u0016",
  "\u0017": "\\u0017",
  "\u0018": "\\u0018",
  "\u0019": "\\u0019",
  "\u001A": "\\u001A",
  "\u001B": "\\u001B",
  "\u001C": "\\u001C",
  "\u001D": "\\u001D",
  "\u001E": "\\u001E",
  "\u001F": "\\u001F",
  "\u007F": "\\u007F",
  "\u0080": "\\u0080",
  "\u0081": "\\u0081",
  "\u0082": "\\u0082",
  "\u0083": "\\u0083",
  "\u0084": "\\u0084",
  "\u0085": "\\u0085",
  "\u0086": "\\u0086",
  "\u0087": "\\u0087",
  "\u0088": "\\u0088",
  "\u0089": "\\u0089",
  "\u008A": "\\u008A",
  "\u008B": "\\u008B",
  "\u008C": "\\u008C",
  "\u008D": "\\u008D",
  "\u008E": "\\u008E",
  "\u008F": "\\u008F",
  "\u0090": "\\u0090",
  "\u0091": "\\u0091",
  "\u0092": "\\u0092",
  "\u0093": "\\u0093",
  "\u0094": "\\u0094",
  "\u0095": "\\u0095",
  "\u0096": "\\u0096",
  "\u0097": "\\u0097",
  "\u0098": "\\u0098",
  "\u0099": "\\u0099",
  "\u009A": "\\u009A",
  "\u009B": "\\u009B",
  "\u009C": "\\u009C",
  "\u009D": "\\u009D",
  "\u009E": "\\u009E",
  "\u009F": "\\u009F"
};
export const escapeJsonString = str => str.replace(/[\"\\\/\u0000-\u001F\u007F\u0080-\u009F]/g, match=>chars[match]);

Note that \b \f \n \r \t are not listed as already matched by \u0008 \u000C \u000A \u000D \u0009 respectively.

The proposed code is expected to be in a JS module due to the bulky chars replacement map, but you can also remove the export and add it all in a function if you prefer.

Upvotes: 1

Eamonn Kenny
Eamonn Kenny

Reputation: 2072

I was struggling with this for complicated mixtures of strings, lists and dictionarys wrapped in JSON.

The simple answer is, don't do anything! Use:

 json.dumps( item, indent=4 )

where item is for instance a dictionary of dictionary of strings and lists and it will escape everything for you itself. This will also result in pretty print output that is human readable.

Example of a part of a dictionary of dictionaries containing lists with special forward slash character:

        {
            "MEASUREMENT": [
                "1\u20444 cup"
            ],
            "DESCRIPTION": [
                "dried"
            ],
            "INGREDIENT": [
                "cranberries"
            ]
        },

It does the right thing for \n replacing it with \\n and so forth. You don't want to escape strings that don't need escaping so let dumps do it for you.

Upvotes: 0

Sanju Kaniyamattam
Sanju Kaniyamattam

Reputation: 505

Use encodeURIComponent() to encode the string.

Eg.:

var product_list = encodeURIComponent(JSON.stringify(product_list));

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

Upvotes: -5

Ruben
Ruben

Reputation: 1091

Using template literals...

var json = `{"1440167924916":{"id":1440167924916,"type":"text","content":"It's a test!"}}`;

Upvotes: -5

4T2G
4T2G

Reputation: 53

To allow single quotes within doubule quoted string for the purpose of json, you double the single quote. {"X": "What's the question"} ==> {"X": "What''s the question"}

https://codereview.stackexchange.com/questions/69266/json-conversion-to-single-quotes

The \' sequence is invalid.

Upvotes: -7

David Knipe
David Knipe

Reputation: 3444

Everyone is talking about how to escape ' in a '-quoted string literal. There's a much bigger issue here: single-quoted string literals aren't valid JSON. JSON is based on JavaScript, but it's not the same thing. If you're writing an object literal inside JavaScript code, fine; if you actually need JSON, you need to use ".

With double-quoted strings, you won't need to escape the '. (And if you did want a literal " in the string, you'd use \".)

Upvotes: 53

Luigi D'Amico
Luigi D'Amico

Reputation: 701

The answer the direct question:
To be safe, replace the required character with \u+4-digit-hex-value

Example: If you want to escape the apostrophe ' replace with \u0027
D'Amico becomes D\u0027Amico

NICE REFERENCE: http://es5.github.io/x7.html#x7.8.4

https://mathiasbynens.be/notes/javascript-escapes

Upvotes: -2

AlexB
AlexB

Reputation: 7416

A JSON string must be double-quoted, according to the specs, so you don't need to escape '.
If you have to use special character in your JSON string, you can escape it using \ character.

See this list of special character used in JSON :

\b  Backspace (ascii code 08)
\f  Form feed (ascii code 0C)
\n  New line
\r  Carriage return
\t  Tab
\"  Double quote
\\  Backslash character


However, even if it is totally contrary to the spec, the author could use \'.

This is bad because :

  • It IS contrary to the specs
  • It is no-longer JSON valid string

But it works, as you want it or not.

For new readers, always use a double quotes for your json strings.

Upvotes: 353

Kickass
Kickass

Reputation: 1134

Most of these answers either does not answer the question or is unnecessarily long in the explanation.

OK so JSON only uses double quotation marks, we get that!

I was trying to use JQuery AJAX to post JSON data to server and then later return that same information. The best solution to the posted question I found was to use:

var d = {
    name: 'whatever',
    address: 'whatever',
    DOB: '01/01/2001'
}
$.ajax({
    type: "POST",
    url: 'some/url',
    dataType: 'json',
    data: JSON.stringify(d),
    ...
}

This will escape the characters for you.

This was also suggested by Mark Amery, Great answer BTW

Hope this helps someone.

Upvotes: 7

YankTHEcode
YankTHEcode

Reputation: 652

May be i am too late to the party but this will parse/escape single quote (don't want to get into a battle on parse vs escape)..

JSON.parse("\"'\"")

Upvotes: 1

Bart
Bart

Reputation: 179

regarding AlexB's post:

 \'  Apostrophe or single quote
 \"  Double quote

escaping single quotes is only valid in single quoted json strings
escaping double quotes is only valid in double quoted json strings

example:

'Bart\'s car'       -> valid
'Bart says \"Hi\"'  -> invalid

Upvotes: -20

Related Questions