Regular Expression to add double quotes around keys in JavaScript

I was trying to solve the same problem using a regEx in Javascript. I have an app written for Node.js to parse incoming JSON, but wanted a "relaxed" version of the parser (see following comments), since it is inconvenient to put quotes around every key (name). Here is my solution:

var objKeysRegex = /({|,)(?:\s*)(?:')?([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*)(?:')?(?:\s*):/g;// look for object names
var newQuotedKeysString = originalString.replace(objKeysRegex, "$1\"$2\":");// all object names should be double quoted
var newObject = JSON.parse(newQuotedKeysString);

Here's a breakdown of the regEx:

  • ({|,) looks for the beginning of the object, a { for flat objects or , for embedded objects.
  • (?:\s*) finds but does not remember white space
  • (?:')? finds but does not remember a single quote (to be replaced by a double quote later). There will be either zero or one of these.
  • ([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) is the name (or key). Starts with any letter, underscore, $, or dot, followed by zero or more alpha-numeric characters or underscores or dashes or dots or $.
  • the last character : is what delimits the name of the object from the value.

Now we can use replace() with some dressing to get our newly quoted keys:

originalString.replace(objKeysRegex, "$1\"$2\":")

where the $1 is either { or , depending on whether the object was embedded in another object. \" adds a double quote. $2 is the name. \" another double quote. and finally : finishes it off. Test it out with

{keyOne: "value1", $keyTwo: "value 2", key-3:{key4:18.34}}

output:

{"keyOne": "value1","$keyTwo": "value 2","key-3":{"key4":18.34}}

Some comments:

  • I have not tested this method for speed, but from what I gather by reading some of these entries is that using a regex is faster than eval()
  • For my application, I'm limiting the characters that names are allowed to have with ([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) for my 'relaxed' version JSON parser. If you wanted to allow more characters in names (you can do that and still have valid JSON), you could instead use ([^'":]+) to mean anything other than double or single quotes or a colon. This would still limit you further than the JSON standard (which allows single quotes in the name) but then you wouldn't be able to parse using this method. You can have all sorts of stuff in here with this expression ([^'":]+), so be careful.

Hope this helps.


This regex will do the trick

$json = preg_replace('/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/','$1"$3":',$json);

It's a php though! I assume it's not a problem converting it to JS.


edit — came back to point out, first and foremost, that this is not a problem that can be solved with a regular expression.

It's important to distinguish between JSON notation as a serialized form, and JavaScript object constant notation.

This:

{ x: "hello" }

is a perfectly valid JavaScript value (an expression fragment), so that this:

var y = { x: "hello" };

gives you exactly the same result as:

var y = { "x": "hello" };

In other words, the value of "y" in either of those cases will be exactly the same. Completely, exactly the same, such that it would not be possible to ever tell which of those two constants was used to initialize "y".

Now, if what you want to do is translate a string containing JavaScript style "JSON shorthand" without quotes into valid JSON, the only thing to do is parse it and reconstruct the string with quotes around the property names. That is, you will have to either write your own "relaxed" JSON parser than can cope with unquoted identifiers as property names, or else find an off-the-shelf parser that can handle such relaxed syntax.

In your case, it looks like once you have the "relaxed" parser available, you're done; there shouldn't be any need for you to translate back. Thankfully, your "invalid" JSON response is completely interpretable by JavaScript itself, so if you trust the data source (and that's a big "if") you should be able to evaluate it with "eval()".