633

Something like:

var jsonString = '{ "Id": 1, "Name": "Coke" }';

//should be true
IsJsonString(jsonString);

//should be false
IsJsonString("foo");
IsJsonString("<div>foo</div>")

The solution should not contain try/catch. Some of us turn on "break on all errors" and they don't like the debugger breaking on those invalid JSON strings.

Chris Martin
  • 28,558
  • 6
  • 66
  • 126
Chi Chan
  • 9,863
  • 8
  • 30
  • 51
  • 29
    Is there a valid reason to not use `try`? – Nick T Aug 13 '13 at 06:12
  • 7
    @NickT Because if you turn on "break on all errors" in the debugger, it will. Chrome now has the option of breaking on uncaught errors tho. – Chi Chan Aug 13 '13 at 14:00
  • 2
    For those curious, here is how the V8 engine does its JSON Parsing: http://v8.googlecode.com/svn/trunk/src/json-parser.h – A T Sep 07 '14 at 07:57
  • 6
    Use just 2 lines to check it with try catch. var isValidJSON = true; try { JSON.parse(jsonString) } catch { isValidJSON = false; } – efkan Aug 30 '16 at 18:29
  • Also I'd answered overhere: http://stackoverflow.com/a/39236371/3765109 – efkan Jan 04 '17 at 17:16
  • 19
    While that works, it's terribly kludgy and bad practice. Try/catch is meant for exceptional behavior and error handling, not general program flow. – Tasgall Jun 26 '17 at 19:31
  • 14
    @Tasgall As a general rule, yes. But what do you do if the try/catch approach is more performant than any validator-based approach? Go with the (sometimes significantly) slower option just because the alternative is "bad practice"? There's nothing functionally wrong with the try/catch method, so there's no reason not to use it. It's important to have new programmers develop good coding standards, but it's equally important to not reinforce blind adherence to conventional guidelines, especially in cases where the guidelines make things more difficult than they need to be. – Abion47 Aug 15 '18 at 17:53
  • Possible duplicate of [AJAX: Check if a string is JSON?](https://stackoverflow.com/questions/2313630/ajax-check-if-a-string-is-json) – Mehdi Dehghani Mar 16 '19 at 06:23

25 Answers25

1062

Use a JSON parser like JSON.parse:

function IsJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}
Gumbo
  • 594,236
  • 102
  • 740
  • 814
  • 8
    Thank you, but I just ran this with the team and they want something that doesn't use try/catch. The question is edited along with a new title. Sorry about that. – Chi Chan Sep 14 '10 at 15:26
  • 1
    Hm... Strange... I used this example and it works fine for me (JSON object from PHP's `json_encode` passes as valid), but it doesn't work for the example in question: `{ "Id": 1, "Name": "Coke" }`. It returns `false` for me. – trejder Sep 29 '12 at 09:16
  • 4
    @trejder: it does that because 1 is not a string, try it with "1" – Purefan Mar 04 '14 at 23:47
  • @trejder Did you pass it as a JavaScript string or as a JavaScript object? Because only the former works. – Gumbo Mar 05 '14 at 05:49
  • 41
    @Gumbo My comment is 1,5 year old! :] I don't remember, what I was doing two weeks ago and you asking me to recall that project? :] No, way... :] – trejder Mar 05 '14 at 09:25
  • @trejder It was just a reply to @Purefan’s comment as `JSON.parse('{ "Id": 1, "Name": "Coke" }')` (string) should work in contrast to `JSON.parse({ "Id": 1, "Name": "Coke" })` (object). – Gumbo Mar 05 '14 at 09:51
  • This is a reliable technique. However, you should be weary of using this in most exception handling cases, especially within loop constructs. That said, this is very simple and works great! – jwize Sep 27 '14 at 21:11
  • 10
    The problem with this answer is, if the string does check out, and you parse it, you'll have parsed it twice. Couldn't you instead return false on a bad parse, but return the object on success? – Carcigenicate Feb 29 '16 at 00:05
  • 5
    @Carcigenicate You could do that. However, `JSON.parse("false")` evaluates to *false* as well. – Gumbo Mar 01 '16 at 19:54
  • 1
    You should consider to add a type check at the start of your function, because if it's not a string, it cannot be a valid json if( typeof( str ) !== 'string' ) { return false; } – Simone Poggi Aug 16 '16 at 13:50
  • @Carcigenicate Totally agree. declare a variable outside the try catch then `varname = JSON.parse(jsonstr);` so you don't have to parse twice – Kolob Canyon Apr 04 '17 at 22:56
  • Using this is better as regex is usually slower. – Krishnadas PC Dec 23 '17 at 13:24
  • 1
    This answer will return TRUE even if the str is a simple "12345678". You should add the typeof checker. – user3651476 Sep 27 '19 at 02:10
  • 1
    @user3651476 That's because "12345678" is a valid json string. JSON documents have a single root node, which can be null, a boolean, a number, a string, an array or an object. – SvenM Feb 18 '20 at 14:19
  • @llamacorn It doesn't answer the question, because it actually does use try/catch. – wvdz Apr 02 '20 at 19:51
479

I know i'm 3 years late to this question, but I felt like chiming in.

While Gumbo's solution works great, it doesn't handle a few cases where no exception is raised for JSON.parse({something that isn't JSON})

I also prefer to return the parsed JSON at the same time, so the calling code doesn't have to call JSON.parse(jsonString) a second time.

This seems to work well for my needs:

function tryParseJSON (jsonString){
    try {
        var o = JSON.parse(jsonString);

        // Handle non-exception-throwing cases:
        // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
        // but... JSON.parse(null) returns null, and typeof null === "object", 
        // so we must check for that, too. Thankfully, null is falsey, so this suffices:
        if (o && typeof o === "object") {
            return o;
        }
    }
    catch (e) { }

    return false;
};
Lynn
  • 8,876
  • 38
  • 66
Matt H.
  • 9,246
  • 8
  • 41
  • 60
  • 12
    Of the answers on the page, this is the most robust and reliable. – Jonline May 30 '14 at 17:07
  • 32
    `o && o !== null` is superfluous. – Aleksei Matiushkin Oct 21 '14 at 15:21
  • 4
    So is using triple-equals with typeof, which always returns a string. :) – Hein Haraldson Berg Dec 03 '14 at 16:09
  • 7
    Despite being an old post, I thought it worthwhile to put a [fiddle](https://jsfiddle.net/karlbateman/Lft2bzf1/) up demonstrating your answer @matth, please note that objects won't be valid.. you must pass a JSON string. Might come in handy for anyone starting out I guess. – stackunderflow May 25 '16 at 14:18
  • A nice addition that allows 'relaxed' JSON parsing. https://github.com/json5/json5 – gkiely Sep 06 '16 at 22:19
  • @Yawz makes a good point. You've already declared `var o`, so checking `ìf(o)` shouldn't be necessary, right? #necropost – Phil Tune Sep 16 '17 at 03:26
  • 5
    The function should return `undefined`, not `false` because `false` is a valid json string and there is no way to differentiate between `tryParseJSON("false")` and `tryParseJSON("garbage")` – sparebytes Feb 22 '18 at 17:32
  • 2
    How this got 300+ upvotes?? Worst than @sparebytes stated, this answer only works for stringified JSON objects!! It will return false for `tryParse("true"), `tryParse("123")`, etc. This approach doesn't make sense. If you just want to check for valid JSON string, use @Gumbo's solution. If you want to use the result of the parse, just parse it and use it, treat exception if thrown. – Andre Figueiredo Apr 16 '18 at 15:46
  • @MindVox, is there a reason why the result box on the fiddle is on the far bottom right of the screen? Took me a while before I saw that. – Gellie Ann Jul 24 '18 at 08:23
  • @GellieAnn It was a while ago, feel free to produce another :-) – stackunderflow Aug 27 '18 at 14:29
  • @Hein Haraldson Berg why shouldn't it? Triple equal is more performant. You should always use it, and use the == only in the few cases where the type isn't certain https://stackoverflow.com/questions/8044750/javascript-performance-difference-between-double-equals-and-triple-equals – massic80 Jul 26 '19 at 13:31
  • @massic80 It’s a comment to Aleksei’s comment (the one directly above mine). And as people point out in the thread you’re linking to, this is meaningless micro optimization that you’ll never actually be able to notice as a mere human. Also, in this case the types are the same, and a proper JS engine will give you exactly the same performance. – Hein Haraldson Berg Jul 26 '19 at 13:40
  • @Hein Haraldson Berg yes, the enhancement is trivial, but also adding one more byte-long character doesn't hurt :) It's good practice, specially looking forward to virtually-typed languages like Typescript. The == could bring to unexpected results with _special_ values. – massic80 Jul 26 '19 at 13:52
  • Back to the answer, what do you think of the more compact `try { const o = JSON.parse(jsonString); return (typeof o === 'object' && o); } catch (e) { return false; }` the second `return` is in the catch, there is no need of it out of the try/catch. `o` (or `false`) is directly returned by the comparison (`o` is in the second place). – massic80 Jul 26 '19 at 14:04
  • @sparebytes There are some other good comments [here](https://stackoverflow.com/questions/58965352/) on the topic of returning false versus undefined. – Lonnie Best Nov 21 '19 at 18:46
  • `"1234"` is perfectly valid JSON. – I wrestled a bear once. Feb 03 '20 at 15:12
188

A comment first. The question was about not using try/catch.
If you do not mind to use it, read the answer below. Here we just check a JSON string using a regexp, and it will work in most cases, not all cases.

Have a look around the line 450 in https://github.com/douglascrockford/JSON-js/blob/master/json2.js

There is a regexp that check for a valid JSON, something like:

if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

  //the json is ok

}else{

  //the json is not ok

}

EDIT: The new version of json2.js makes a more advanced parsing than above, but still based on a regexp replace ( from the comment of @Mrchief )

Liam
  • 22,818
  • 25
  • 93
  • 157
Mic
  • 23,536
  • 8
  • 55
  • 69
  • 66
    This is only checking if the code is safe for eval to use. For example the following string '2011-6-27' would pass that test. – SystemicPlural Jul 27 '11 at 16:22
  • 4
    @SystemicPlural, yes but the question was about not using try/catch – Mic Jul 25 '13 at 10:33
  • http://stackoverflow.com/questions/546433/regular-expression-to-match-outer-brackets – Christophe Roussy Aug 02 '13 at 13:45
  • @PetrPeller the question was about not using try/catch, do you have another suggestion? – Mic May 27 '14 at 22:06
  • 10
    You cannot test whether a string is valid JSON with a regex in JavaScript, since JS regexes don't support the necessary extensions (recursive regexes) that let you do so. Your above code fails on "{". – Venge Jun 01 '14 at 22:12
  • @Venge, this code comes from json2.js of Douglas Crockford. Which was the way to read a JSON cross browser before it was native. So I suppose it is good enough for most cases. Bear in mind the question dates from 2010. – Mic Jun 03 '14 at 12:35
  • 1
    @Mic I commented because your answers says it's a way to check if JSON is valid, but that regex only checks if it's safe to eval(). – Venge Jun 05 '14 at 17:27
  • Hi,I am using Kendo ui inline editing grid and do custom validation for check that string is in json format or not .I put your json validation format but i got error that **text is not defined** – Ajisha Feb 06 '15 at 06:19
  • @Ajisha, you need to replace `text.replace` in the code by something like `yourString.replace`. `yourString` being the string you want to check – Mic Feb 06 '15 at 23:03
  • 2
    @Mic json2.js no longer uses that simple check (instead uses a 4 stage parsing to determine valid JSON). Would suggest to revise or remove your answer. Note that I don't think there's anythign wrong with "not having a try/catch as the sole mechanism to check for JSON" as an approach. – Mrchief Jun 20 '16 at 18:21
  • @Mrchief, this question is funny. For reasons that escapes me too, the guy didn't want to use try/catch, and this was an answer... 6 years ago that helped him. Why should it change? – Mic Jun 21 '16 at 22:15
  • 9
    Just because it helps him, doesn't mean it helps the rest of us, who, years later, have the same question. – McKay Aug 11 '16 at 17:36
  • You should consider changing the function name to start with a lower case. e.g.: isJsonString – Gabri Botha Sep 07 '16 at 10:42
  • 2
    `JSON.parse` is much faster, does the job in ~0,2ms while this if comparison takes ~0,9ms. – Machado Aug 24 '17 at 11:44
  • I'm sorry but this is just super brittle and not very maintainable. Why not use the parser itself? – Jakub Keller Apr 22 '20 at 14:09
  • @JakubKeller, because the question was: ... without using try/catch. Have a look at the response below if you want to use the parser. – Mic Apr 23 '20 at 15:26
61
// vanillaJS
function isJSON(str) {
    try {
        return (JSON.parse(str) && !!str);
    } catch (e) {
        return false;
    }
}

Usage: isJSON({}) will be false, isJSON('{}') will be true.

To check if something is an Array or Object (parsed JSON):

// vanillaJS
function isAO(val) {
    return val instanceof Array || val instanceof Object ? true : false;
}

// ES2015
var isAO = (val) => val instanceof Array || val instanceof Object ? true : false;

Usage: isAO({}) will be true, isAO('{}') will be false.

Machado
  • 5,010
  • 4
  • 34
  • 44
moeiscool
  • 1,014
  • 10
  • 12
38

Here my working code:

function IsJsonString(str) {
  try {
    var json = JSON.parse(str);
    return (typeof json === 'object');
  } catch (e) {
    return false;
  }
}
Barmar
  • 596,455
  • 48
  • 393
  • 495
Anand Kumar
  • 419
  • 4
  • 2
  • 2
    IsJsonString(null); //returns true. It can be fixed by comparing `typeof str === 'string'` – gramcha Nov 26 '19 at 08:54
  • 1
    `null` represents the empty value of an `object`, so this looks ok from my point of view... it might not apply to your specific scenario, but it is what it is – HellBaby Nov 06 '20 at 08:18
29

I used a really simple method to check a string how it's a valid JSON or not.

function testJSON(text){
    if (typeof text!=="string"){
        return false;
    }
    try{
        JSON.parse(text);
        return true;
    }
    catch (error){
        return false;
    }
}

Result with a valid JSON string:

var input='["foo","bar",{"foo":"bar"}]';
testJSON(input); // returns true;

Result with a simple string;

var input='This is not a JSON string.';
testJSON(input); // returns false;

Result with an object:

var input={};
testJSON(input); // returns false;

Result with null input:

var input=null;
testJSON(input); // returns false;

The last one returns false because the type of null variables is object.

This works everytime. :)

kukko
  • 525
  • 9
  • 17
  • 1
    JSON.parse(null), JSON.parse("false") doesn't throw errors, probably there are more examples – klodoma Mar 15 '18 at 10:18
  • Yeah, you are right, I forgot to check how the input is a string or not, If I do that, this method with `null` input it gives back false. But the "false" input is a valid JSON string. This will be parsed to `boolean (false)`. Now I modify the code to be more accurate. – kukko Mar 16 '18 at 08:36
18

In prototypeJS, we have method isJSON. You can try that. Even json might help.

"something".isJSON();
// -> false
"\"something\"".isJSON();
// -> true
"{ foo: 42 }".isJSON();
// -> false
"{ \"foo\": 42 }".isJSON();
// -> true
Community
  • 1
  • 1
Ifi
  • 492
  • 1
  • 4
  • 12
  • 9
    Thanks, but I think using the prototype library to do this is a little overkilled. – Chi Chan Sep 14 '10 at 15:29
  • 4
    You gave FOUR examples but only THREE results. What is the result for `"{ foo: 42 }".isJSON()`? If `false`, as I assume (result should follow function it document), then good question is, why it is false? `{ foo: 42 }` seems to be perfectly valid JSON. – trejder Sep 29 '12 at 09:58
  • 4
    @trejder Unfortunately, the JSON spec requires quoted keys. – mikermcneil Oct 08 '12 at 01:27
  • 4
    And "2002-12-15".isJSON returns true, while JSON.parse("2002-12-15") throws an error. – ychaouche Nov 13 '12 at 17:14
  • 4
    I think the better answer here would be to pull that function out of the prototype library and place it here. Especially since http://api.prototypejs.org/language/string/prototype/isjson/ is 404. – jcollum May 28 '13 at 17:53
6

Here is the typescript version too:

JSONTryParse(input: any) {
    try {
        //check if the string exists
        if (input) {
            var o = JSON.parse(input);

            //validate the result too
            if (o && o.constructor === Object) {
                return o;
            }
        }
    }
    catch (e: any) {
    }

    return false;
};
Zameer Ansari
  • 23,672
  • 19
  • 120
  • 191
5

From Prototype framework String.isJSON definition here

/**
   *  String#isJSON() -> Boolean
   *
   *  Check if the string is valid JSON by the use of regular expressions.
   *  This security method is called internally.
   *
   *  ##### Examples
   *
   *      "something".isJSON();
   *      // -> false
   *      "\"something\"".isJSON();
   *      // -> true
   *      "{ foo: 42 }".isJSON();
   *      // -> false
   *      "{ \"foo\": 42 }".isJSON();
   *      // -> true
  **/
  function isJSON() {
    var str = this;
    if (str.blank()) return false;
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    return (/^[\],:{}\s]*$/).test(str);
  }

so this is the version that can be used passing a string object

function isJSON(str) {
    if ( /^\s*$/.test(str) ) return false;
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    return (/^[\],:{}\s]*$/).test(str);
  }

function isJSON(str) {
    if ( /^\s*$/.test(str) ) return false;
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    return (/^[\],:{}\s]*$/).test(str);
  }

console.log ("this is a json",  isJSON( "{ \"key\" : 1, \"key2@e\" : \"val\"}" ) )

console.log("this is not a json", isJSON( "{ \"key\" : 1, \"key2@e\" : pippo }" ) )
loretoparisi
  • 12,864
  • 9
  • 78
  • 108
  • 1
    Anyone have test suite for comparing all these answers? I'd like to see if this one is correct. – Lonnie Best Nov 21 '19 at 18:58
  • 1
    @LonnieBest good point. My 2 cents. I have used for years in production and it has always worked fine and with a reasonable execution time. – loretoparisi Nov 21 '19 at 22:18
5
  • isValidJsonString - check for valid json string

  • JSON data types - string, number, object (JSON object), array, boolean, null (https://www.json.org/json-en.html)

  • falsy values in javascript - false, 0, -0, 0n, ", null, undefined, NaN - (https://developer.mozilla.org/en-US/docs/Glossary/Falsy)

  • JSON.parse

    • works well for number , boolean, null and valid json String won't raise any error. please refer example below

      • JSON.parse(2) // 2
      • JSON.parse(null) // null
      • JSON.parse(true) // true
      • JSON.parse('{"name":"jhamman"}') // {name: "jhamman"}
      • JSON.parse('[1,2,3]') // [1, 2, 3]
    • break when you parse undefined , object, array etc

      • it gave Uncaught SyntaxError: Unexpected end of JSON input . please refer example below
      • JSON.parse({})
      • JSON.parse([])
      • JSON.parse(undefined)
      • JSON.parse("jack")
function isValidJsonString(jsonString){
    
    if(!(jsonString && typeof jsonString === "string")){
        return false;
    }

    try{
       JSON.parse(jsonString);
       return true;
    }catch(error){
        return false;
    }

}

4

This answer to reduce the cost of trycatch statement.

I used JQuery to parse JSON strings and I used trycatch statement to handle exceptions, but throwing exceptions for un-parsable strings slowed down my code, so I used simple Regex to check the string if it is a possible JSON string or not without going feather by checking it's syntax, then I used the regular way by parsing the string using JQuery :

if (typeof jsonData == 'string') {
    if (! /^[\[|\{](\s|.*|\w)*[\]|\}]$/.test(jsonData)) {
        return jsonData;
    }
}

try {
    jsonData = $.parseJSON(jsonData);
} catch (e) {

}

I wrapped the previous code in a recursive function to parse nested JSON responses.

Rabih
  • 268
  • 1
  • 4
  • 16
4

I think I know why you want to avoid that. But maybe try & catch !== try & catch. ;o) This came into my mind:

var json_verify = function(s){ try { JSON.parse(s); return true; } catch (e) { return false; }};

So you may also dirty clip to the JSON object, like:

JSON.verify = function(s){ try { JSON.parse(s); return true; } catch (e) { return false; }};

As this as encapsuled as possible, it may not break on error.

chrixle
  • 321
  • 3
  • 7
4

Maybe it will useful:

    function parseJson(code)
{
    try {
        return JSON.parse(code);
    } catch (e) {
        return code;
    }
}
function parseJsonJQ(code)
{
    try {
        return $.parseJSON(code);
    } catch (e) {
        return code;
    }
}

var str =  "{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}";
alert(typeof parseJson(str));
alert(typeof parseJsonJQ(str));
var str_b  = "c";
alert(typeof parseJson(str_b));
alert(typeof parseJsonJQ(str_b));

output:

IE7: string,object,string,string

CHROME: object,object,string,string

1
function get_json(txt)
{  var data

   try     {  data = eval('('+txt+')'); }
   catch(e){  data = false;             }

   return data;
}

If there are errors, return false.

If there are no errors, return json data

Emrah Tuncel
  • 426
  • 3
  • 7
  • 4
    In the question: "The solution should not contain try/catch". – ddmps Mar 06 '13 at 03:58
  • 1
    Why? This is guaranteed way... Would be foolish to disuse! I'm sorry for not know English. I used Google Translate – Emrah Tuncel Mar 06 '13 at 23:32
  • Interesting. I'd like to see a performance comparison of JSON.parse versus this eval based solution. Yet this look scary from a security/injection perspective. – Lonnie Best Nov 21 '19 at 19:41
1

You can use the javascript eval() function to verify if it's valid.

e.g.

var jsonString = '{ "Id": 1, "Name": "Coke" }';
var json;

try {
  json = eval(jsonString);
} catch (exception) {
  //It's advisable to always catch an exception since eval() is a javascript executor...
  json = null;
}

if (json) {
  //this is json
}

Alternatively, you can use JSON.parse function from json.org:

try {
  json = JSON.parse(jsonString);
} catch (exception) {
  json = null;
}

if (json) {
  //this is json
}

Hope this helps.

WARNING: eval() is dangerous if someone adds malicious JS code, since it will execute it. Make sure the JSON String is trustworthy, i.e. you got it from a trusted source.

Edit For my 1st solution, it's recommended to do this.

 try {
      json = eval("{" + jsonString + "}");
    } catch (exception) {
      //It's advisable to always catch an exception since eval() is a javascript executor...
      json = null;
    }

To guarantee json-ness. If the jsonString isn't pure JSON, the eval will throw an exception.

Buhake Sindi
  • 82,658
  • 26
  • 157
  • 220
  • First example using eval says that "
    foo
    " is valid JSON. It may work differently in different browsers, but it appears that in FireFox, eval() accepts XML.
    – Mark Lutton Sep 14 '10 at 15:26
  • Thank you, but I just ran this with the team and they want something that doesn't use try/catch. The question is edited along with a new title. Sorry about that. – Chi Chan Sep 14 '10 at 15:26
  • @Mark Lutton, the object type won't be of JSON but of XML Dom Document (I forgot what the exact type in firefox is). – Buhake Sindi Sep 14 '10 at 15:30
  • @Chi Chan. You can use option 2 without using try/catch. Without using try/catch you basically allowing harm to come to your program. – Buhake Sindi Sep 14 '10 at 15:32
  • 1
    eval also accepts valid JavaScript, like "alert(5);" and strings in single quotes, which are not valid JSON. – Mark Lutton Sep 14 '10 at 15:48
  • Hey Gentleman :), What I wanted isn't just the without using the try/catch block. That will throw an error and we don't want THAT. What I meant was checking for the string without doing a try/catch. Some of us have the debugger set to break on all exceptions (even if it's catched) and breaking everytime we get a non json string is not ideal. – Chi Chan Sep 14 '10 at 15:50
  • @Mark Lutton, I hope you read my warning sentence. I said that eval executes Javascript code so `alert(5)` is valid for eval. Check my updated post. – Buhake Sindi Sep 14 '10 at 15:53
  • @Chi Chan, use JSON.org's `JSON.parse` instead. My 2nd example shows just that. – Buhake Sindi Sep 14 '10 at 15:54
  • Hey Gentleman, Yup, that's what I ended up using with a little modification to the code. JSON.parse will throw "SyntaxError('JSON.parse');" for an invalid json string, hence I added a little modification to it. – Chi Chan Sep 14 '10 at 16:01
  • Avoid using eval(). – Ricardo Alamino Apr 05 '18 at 20:41
  • If `eval()` is completely necessary, you should use `new Function()` if your code works with it. – GalaxyCat105 Jul 10 '20 at 15:57
1

var jsonstring='[{"ConnectionString":"aaaaaa","Server":"ssssss"}]';

if(((x)=>{try{JSON.parse(x);return true;}catch(e){return false}})(jsonstring)){

document.write("valide json")

}else{
document.write("invalide json")
}
safi eddine
  • 349
  • 3
  • 9
1

I infer from the opening comment that the use case is delineating whether a response is HTML or JSON. In which case, when you do receive JSON, you probably ought to be parsing it and handling invalid JSON at some point in your code anyway. Aside from anything, I imagine you would like to be informed by your browser should JSON be expected but invalid JSON received (as will users by proxy of some meaningful error message)!

Doing a full regex for JSON is unnecessary therefore (as it would be - in my experience - for most use-cases). You would probably be better off using something like the below:

function (someString) {
  // test string is opened with curly brace or machine bracket
  if (someString.trim().search(/^(\[|\{){1}/) > -1) {
    try { // it is, so now let's see if its valid JSON
      var myJson = JSON.parse(someString);
      // yep, we're working with valid JSON
    } catch (e) {
      // nope, we got what we thought was JSON, it isn't; let's handle it.
    }
  } else {
    // nope, we're working with non-json, no need to parse it fully
  }
}

that should save you having to exception handle valid non-JSON code and take care of duff json at the same time.

Jay Edwards
  • 712
  • 8
  • 17
  • This hybrid solution seems like it would be an efficient way to avoid having to do a try catch in most non-JSON cases. I like that aspect of your approach. – Lonnie Best Nov 21 '19 at 19:14
1
if(resp) {
    try {
        resp = $.parseJSON(resp);
        console.log(resp);
    } catch(e) {
        alert(e);
    }
}

hope this works for you too

Darkcoder
  • 636
  • 7
  • 15
1

I thought I'd add my approach, in the context of a practical example. I use a similar check when dealing with values going in and coming out of Memjs, so even though the value saved may be string, array or object, Memjs expects a string. The function first checks if a key/value pair already exists, if it does then a precheck is done to determine if value needs to be parsed before being returned:

  function checkMem(memStr) {
    let first = memStr.slice(0, 1)
    if (first === '[' || first === '{') return JSON.parse(memStr)
    else return memStr
  }

Otherwise, the callback function is invoked to create the value, then a check is done on the result to see if the value needs to be stringified before going into Memjs, then the result from the callback is returned.

  async function getVal() {
    let result = await o.cb(o.params)
    setMem(result)
    return result

    function setMem(result) {
      if (typeof result !== 'string') {
        let value = JSON.stringify(result)
        setValue(key, value)
      }
      else setValue(key, result)
    }
  }

The complete code is below. Of course this approach assumes that the arrays/objects going in and coming out are properly formatted (i.e. something like "{ key: 'testkey']" would never happen, because all the proper validations are done before the key/value pairs ever reach this function). And also that you are only inputting strings into memjs and not integers or other non object/arrays-types.

async function getMem(o) {
  let resp
  let key = JSON.stringify(o.key)
  let memStr = await getValue(key)
  if (!memStr) resp = await getVal()
  else resp = checkMem(memStr)
  return resp

  function checkMem(memStr) {
    let first = memStr.slice(0, 1)
    if (first === '[' || first === '{') return JSON.parse(memStr)
    else return memStr
  }

  async function getVal() {
    let result = await o.cb(o.params)
    setMem(result)
    return result

    function setMem(result) {
      if (typeof result !== 'string') {
        let value = JSON.stringify(result)
        setValue(key, value)
      }
      else setValue(key, result)
    }
  }
}
0

Oh you can definitely use try catch to check whether its or not a valid JSON

Tested on Firfox Quantom 60.0.1

use function inside a function to get the JSON tested and use that output to validate the string. hears an example.

    function myfunction(text){

       //function for validating json string
        function testJSON(text){
            try{
                if (typeof text!=="string"){
                    return false;
                }else{
                    JSON.parse(text);
                    return true;                            
                }
            }
            catch (error){
                return false;
            }
        }

  //content of your real function   
        if(testJSON(text)){
            console.log("json");
        }else{
            console.log("not json");
        }
    }

//use it as a normal function
        myfunction('{"name":"kasun","age":10}')
Aylian Craspa
  • 332
  • 3
  • 11
0

The function IsJsonString(str), that is using JSON.parse(str), doesn't work in my case.
I tried to validate json output from GraphiQL it always return false. Lucky me, isJSON works better:

var test = false;

$('body').on('DOMSubtreeModified', '.resultWrap', function() {

    if (!test) {   
        var resultWrap = "{" + $('#graphiql .resultWrap').text().split("{").pop();
        if isJSON(resultWrap) {test = !test;}
        console.log(resultWrap); 
        console.log(resultWrap.isJSON());
    }

});

Sample output:

THREE.WebGLRenderer 79
draw.js:170 {xxxxxxxxxx​
draw.js:170 false
draw.js:170 {xxxxxxxxxx ​
draw.js:170 false
draw.js:170 {xxxxxxxxxx ​
draw.js:170 false
draw.js:170 {xxxxxxxxxx ​
draw.js:170 false
draw.js:170 {​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,  "height": 327​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,  "height": 327}​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,  "height": 327}
draw.js:170 true

Chetabahana
  • 7,806
  • 2
  • 50
  • 70
0

For people who like the .Net convention of "try" functions that return a boolean and handle a byref param containing the result. If you don't need the out parameter you can omit it and just use the return value.

StringTests.js

  var obj1 = {};
  var bool1 = '{"h":"happy"}'.tryParse(obj1); // false
  var obj2 = {};
  var bool2 = '2114509 GOODLUCKBUDDY 315852'.tryParse(obj2);  // false

  var obj3 = {};
  if('{"house_number":"1","road":"Mauchly","city":"Irvine","county":"Orange County","state":"California","postcode":"92618","country":"United States of America","country_code":"us"}'.tryParse(obj3))
    console.log(obj3);

StringUtils.js

String.prototype.tryParse = function(jsonObject) {
  jsonObject = jsonObject || {};
  try {
    if(!/^[\[{]/.test(this) || !/[}\]]$/.test(this)) // begin / end with [] or {}
      return false; // avoid error handling for strings that obviously aren't json
    var json = JSON.parse(this);
    if(typeof json === 'object'){
      jsonObject.merge(json);
      return true;
    }
  } catch (e) {
    return false;
  }
}

ObjectUtils.js

Object.defineProperty(Object.prototype, 'merge', {
  value: function(mergeObj){
    for (var propertyName in mergeObj) {
      if (mergeObj.hasOwnProperty(propertyName)) {
        this[propertyName] = mergeObj[propertyName];
      }      
    }
    return this;
  },
  enumerable: false, // this is actually the default
});
toddmo
  • 16,852
  • 9
  • 86
  • 91
0

If you're dealing with a response from an AJAX (or XMLHttpRequest) call, what worked for me is to check the response content type and parse or not the content accordingly.

Vinicius
  • 1,363
  • 15
  • 17
0

Just keeping it simple

function isValidJsonString(tester) {
    //early existing
    if(/^\s*$|undefined/.test(tester) || !(/number|object|array|string|boolean/.test(typeof tester))) 
        {
        return false;
    };
//go ahead do you parsing via try catch
return true;

};
Syed
  • 482
  • 1
  • 3
  • 10
-8

Very Simple one-liner code ( But Hacky approach )

if (expected_json.id === undefined){
   // not a json
}
else{
   // json
}

NOTE: This only works if you are expecting something is JSON string like id. I am using it for an API and expecting the result either in JSON or some error string.

Abhishek Goel
  • 15,517
  • 8
  • 81
  • 62