Escaping JSON in Javascript

As more and more of the web moves to using API’s it appears that parsing JSON is becoming a larger part of the code we write.
But there are many scenarios regarding escaping JSON that can be tricky, this article takes a look at what they are, why they happen and how to solve them.

In this article we will be using JSON.parse(), something available with every browser which can run in a console in Developer Tools.


Basics

Lets start with the basics, a JSON string containing a string.

JSON.parse('{"test": { "new object": "First String"}}')

Result: Pass validation
Why: All correctly escaped

Now we move onto a basic string which contains an apostrophe.

JSON.parse('{"test": { "new object": "That's right"}}')

Result: fail validation
Why: The apostrophe will need escaping.

Solving that:
Javascript has deprecated the `escape()` function, so in order to escape strings you must either hand crank it OR find a library which will do it.
A simply way to hand write it is.

string = string.replace(/'/g, "'");

This will replace all instances of apostrophe with a backslash which will produce an escaped string.

After running it through that function it will produce.

JSON.parse('{"test": { "new object": "That\'s right"}}')

Result: Pass validation
Why: All correctly escaped

Below there is an object within the JSON. This relies on the same level of escaping and the above solution would work with strings.

JSON.parse('{"test": {}}')


Sub-JSON strings

Now we move onto a more complicated but common issue. JSON strings inside JSON strings.

JSON.parse('{"test": "{}"}')

Result: Pass validation
Why: String correctly escaped

But what if the sub-JSON string has data?

JSON.parse('{"test": "{key: 100}"}')

Result: Pass validation
Why: String correctly escaped

Produces:

Object {test: "{key: 100}"}

This works fine as there is nothing which requires escaping, its just a clean string holding a key and integer.

But what if we want the value to be a string instead of an integer?

JSON.parse('{"test": "{"myKey":"MyValue"}"}')

Result: Fail validation
Why: The speech marks require escaping.

So lets follow same rule as before and escape the speech marks.

JSON.parse('{"test": \"{\"h\":\"e\"}\"}')

Result: Fail validation
Why: So even though the outer string is escaped, the inner must be double escaped to make up for the \.

Finally we are left with the end result.

JSON.parse('{"test": \"{\\\"h\\\":\\\"e\\\"}\"}')

This is parsed into:

Object {test: "{"h":"e"}"}

Where people have struggled in the past is understanding that the inner JSON will need double escaping and getting any custom escape function to do that can produce hackey code.
The best solution to this is to use a JSON Encoder and not a Javascript Encoder, which will not correctly double encode the inner string.

Leave a Reply