84

My JavaScript sometimes crashes on this line:

var json = eval('(' + this.responseText + ')');

Crashes are caused when the argument of eval() is not JSON. Is there any way to check if the string is JSON before making this call?

I don't want to use a framework - is there any way to make this work using just eval()? (There's a good reason, I promise.)

2

8 Answers 8

157

If you include the JSON parser from json.org, you can use its parse() function and just wrap it in a try/catch, like so:

try
{
   var json = JSON.parse(this.responseText);
}
catch(e)
{
   alert('invalid json');
}

Something like that would probably do what you want.

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

4 Comments

using jQuery.parseJSON(..) you wouldn't need to include json.org
@Raymo OP didn't mention using jQuery and json2.js less than half the size of jQuery (in terms of file size).
Parsing an entire string is bad practice, and throwing an exception can cause lag
it will not throw an exception if you send a number string
22

Hers's the jQuery alternative...

try
{
  var jsonObject = jQuery.parseJSON(yourJsonString);
}
catch(e)
{
  // handle error 
}

Comments

16

I highly recommend you use a javascript JSON library for serializing to and from JSON. eval() is a security risk which should never be used unless you are absolutely certain that its input is sanitized and safe.

With a JSON library in place, just wrap the call to its parse() equivalent in a try/catch-block to handle non-JSON input:

try
{
  var jsonObject = JSON.parse(yourJsonString);
}
catch(e)
{
  // handle error 
}

Comments

2

Maybe this helps: With this code, you can get directly your data…

<!DOCTYPE html>
<html>
<body>

<h3>Open console, please, to view result!</h3>
<p id="demo"></p>

<script>
var tryJSON = function (test) {
	try {
	    JSON.parse(test);
	}
	catch(err) {
    	// maybe you need to escape this… (or not)
	    test = '"'+test.replace(/\\?"/g,'\\"')+'"';
	}
	eval('test = '+test);
	console.debug('Try json:', test);
};

// test with string…
var test = 'bonjour "mister"';
tryJSON(test);
// test with JSON…
var test = '{"fr-FR": "<p>Ceci est un texte en français !</p>","en-GB": "<p>And here, a text in english!</p>","nl-NL": "","es-ES": ""}';
tryJSON(test);
</script>

</body>
</html>

1 Comment

There are a lot of alternative ways to achieve the same result, using eval() is probably be the least appropriate one.
1

The problem with depending on the try-catch approach is that JSON.parse('123') = 123 and it will not throw an exception. Therefore, In addition to the try-catch, we need to check the type as follows:

function isJsonStr(str) {
    var parsedStr = str;
    try {
        parsedStr = JSON.parse(str);
    } catch (e) {
        return false;
    }
    return typeof parsedStr == 'object'
}

Comments

1

!!! All other answers are wrong.

You should be aware of the http protocol standards and follow its rules. That way all developers can communicate without even speaking to each other. When you send a request using AJAX or any other http client, you can use Accept header to indicate which response content type you accept (expect). And then you use Content-Type of the response to identify the data format and deal with it accordingly.

$.ajax({
    type: "POST",
    url: "/api/connect/user",
    headers: {          
        "Content-Type": "application/json; charset=utf-8" // what we send
        "Accept": "application/json, text/plain; charset=utf-8", // what we accept (expect back)
    },
    data: "{ 'field': 'data to be sent' }", 
    success: function(response, status, xhr){ 
        var ct = xhr.getResponseHeader("content-type") || "";
        if (ct.indexOf("text/plain") > -1) {
          // handle text here
        } else if (ct.indexOf("application/json") > -1) {
          // handle json here
        } else {
          throw new Error("Content type " + ct " is not expected/supported.");
        }
    },
    error : function(error) {
        // handle error here
    },
})

Please note that Accept header tells the server what format you accept, so the server can send you the data in the desired format (json, xml, text, html, etc.). Also please be aware that the server could not support some of the content types, that way you should expect 406 and handle it accordingly. I assume you also handle other http statuses properly.

screen1

Comments

0

jQuery $.ajax() will add the responseJSON property to the response object, and to test if the response is JSON, you can use:

if (xhr.hasOwnProperty('responseJSON')) {}

Comments

-1

There is a tiny library that checks JavaScript types: is.js

is.json({foo: 'bar'});
=> true

// functions are returning as false
is.json(toString);
=> false

is.not.json([]);
=> true

is.all.json({}, 1);
=> false

is.any.json({}, 2);
=> true

// 'all' and 'any' interfaces can also take array parameter
is.all.json([{}, {foo: 'bar'}]);
=> true

Actually is.js is much more then this, some honorable mentions:

var obj = document.createElement('div');
is.domNode(obj);
=> true

is.error(new Error());
=> true

is.function(toString);
=> true

is.chrome();
=> true if current browser is chrome


Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.