Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON.stringify / parse oddness with quote marks

I am running into an odd little problem with parsing some JSON which has quotes in it. I am using the native JSON.stringify and JSON.parse functions to do this. If I stringify an object which an object which has quote marks in it, they are escaped as one would expect. If I then parse this back into an object, it again works fine.

The problem is occurring where I stringify, then print the object to a page, then parse the resulting string. If I try to do this, the parse function fails as stringify has only put single slashes before each of the offending quote marks.

The reason I need to achieve this is I am working on an application that dynamically loads content stored in a database as JSON strings. The strings at some point need to be printed onto the page somewhere so that the javascript can find them and build the page based on their contents. I need some way of robustly passing the object into and out of strings which will not fail if a user inputs the wrong characters!

I can solve this for the moment by inserting extra slashes into the code with a replace call, but I was wondering if there is a better way to handle this?

I have put together a couple of jsfiddles to illustrate what I am trying to describe:

http://jsfiddle.net/qwUAJ/ (Stringify then parse back)

var ob = {};
ob["number1"] = 'Number "1"';
ob["number2"] = 'Number 2';
ob["number3"] = 'Number 3';

var string = JSON.stringify(ob);
var reOb = JSON.parse('{"number1":"Number \"1\"","number2":"Number 2","number3":"Number 3"}');

$('div').html(string);

http://jsfiddle.net/a3gBf/4/ (Stringify, then print, then parse back)

// Make an object
var ob = {};
ob["number1"] = 'Number "1"';
ob["number2"] = 'Number 2';
ob["number3"] = 'Number 3';

// Turn the object into a JSON string
var string = JSON.stringify(ob);

// Printing the string outputs
// {"number1":"Number \"1\"","number2":"Number 2","number3":"Number 3"}
$('.stringified').html(string);

// Attempt to turn the printed string back into an object
var reOb = JSON.parse('{"number1":"Number \"1\"","number2":"Number 2","number3":"Number 3"}');

// This fails due to the single escaped quote marks.

Thank you for any help in advance!

like image 881
Gruffy Avatar asked Jan 13 '23 15:01

Gruffy


2 Answers

This is a problem which arises from re-evaluating a String without first converting it back into a string literal, so the meaning changes if it is even still valid.
You need to consider what does '\"' as a literal actually mean? The answer is ", without the \. Why?

  • \" resolves to "

If you want to have \" as the result of the literal, you need to write '\\\"'

  • \\ resolves to \
  • \" resolves to "

So basically, the extra slashes are required to escape any characters with special meaning in string literals.

If you did var reOb = JSON.parse($('.stringified').html()); it would work fine as is.


Consider further

str = '\\\"\\\'';      //      \"\'
str = '\"\'';          //      "'
str = '"'';            // SyntaxError: Unexpected token ILLEGAL

As far as I'm aware, JavaScript offers no native implementation to convert strings as desired, so the easiest method I know of is using a replace

function toLiteral(str) {
    var dict = {'\b': 'b', '\t': 't', '\n': 'n', '\v': 'v', '\f': 'f', '\r': 'r'};
    return str.replace(/([\\'"\b\t\n\v\f\r])/g, function ($0, $1) {
        return '\\' + (dict[$1] || $1);
    });
}
toLiteral('foo\\bar'); // "foo\\bar"
like image 138
Paul S. Avatar answered Jan 16 '23 02:01

Paul S.


If you generate JS with PHP code you should escape the quotes in your JSON string:

//PHP code generating js code
echo "var myJSONString = \"". str_replace("\"","\\\"",$mySqlJSON)."\";";
like image 22
HMR Avatar answered Jan 16 '23 02:01

HMR