1

Thanks for looking!

BACKGROUND

I am writing some front-end code that consumes a JSON service which is returning malformed JSON. Specifically, the keys are not surrounded with quotes:

{foo: "bar"}

I have NO CONTROL over the service, so I am correcting this like so:

var scrubbedJson = dirtyJson.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": ');

This gives me well formed JSON:

{"foo": "bar"}

Problem

However, when I call JSON.parse(scrubbedJson), I still get an error. I suspect it may be because the entire JSON string is surrounded in double quotes but I am not sure.

UPDATE

This has been solved--the above code works fine. I had a rogue single quote in the body of the JSON that was returned. I got that out of there and everything now parses. Thanks. Any help would be appreciated.

8
  • Can you show what's actually returned by the service? Yes, if the entire string is surrounded by double quotes it's still not valid JSON. Commented Aug 16, 2013 at 18:58
  • 1
    Also, can you fix the service? Commented Aug 16, 2013 at 18:59
  • You can assume that the following would be returned: "{"foo":"bar"}". I am terrible with regex. Do you know how this would be cured? Commented Aug 16, 2013 at 18:59
  • Fixing the service is unfortunately not an option. I have no control over it. Commented Aug 16, 2013 at 18:59
  • 1
    You're almost there! You're on the right track preprocessing the JSON, just add another rule to remove the quotes at the beginning and end of the malformed JSON string. Also, if I were you, I would contact the service and send them a link to this question in order to help others, as well as encourage the service to fix the json output! Commented Aug 16, 2013 at 19:11

5 Answers 5

3

You can avoid using a regexp altogether and still output a JavaScript object from a malformed JSON string (keys without quotes, single quotes, etc), using this simple trick:

var jsonify = (function(div){
  return function(json){
    div.setAttribute('onclick', 'this.__json__ = ' + json);
    div.click();
    return div.__json__;
  }
})(document.createElement('div'));

// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)

Here's a demo: http://codepen.io/csuwldcat/pen/dfzsu (open your console)

Sign up to request clarification or add additional context in comments.

Comments

2

something like this may help to repair the json ..

$str='{foo:"bar"}';
echo preg_replace('/({)([a-zA-Z0-9]+)(:)/','$1"$2"${3}',$str);

Output:

{"foo":"bar"}

EDIT:

var str='{foo:"bar"}';
str.replace(/({)([a-zA-Z0-9]+)(:)/,'$1"$2"$3')

2 Comments

not sure why I put it in php ?? var str='{foo:"bar"}';str.replace(/({)([a-zA-Z0-9]+)(:)/,'$1"$2"$3')
Fails on: str = '{foo: "bar", foo2: "{foo:bar}"}'
0

There is a project that takes care of all kinds of invalid cases in JSON https://github.com/freethenation/durable-json-lint

Comments

0

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 be valid), you could instead use ([^'":]+) to mean anything other than double or single quotes or a colon. You can have all sorts of stuff in here with this expression, so be careful.
  • One shortcoming is that this method actually changes the original incoming data (but I think that's what you wanted?). You could program around that to mitigate this issue - depends on your needs and resources available.

Hope this helps. -John L.

Comments

-1

How about?

function fixJson(json) {
    var tempString, tempJson, output;

    tempString = JSON.stringify(json);
    tempJson = JSON.parse(tempString);
    output = JSON.stringify(tempJson);

    return output;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.