801
isJsonString('{ "Id": 1, "Name": "Coke" }')

should be true and

isJsonString('foo')
isJsonString('<div>foo</div>')

should be false.

I'm looking for a solution that doesn't use try/catch because I have my debugger set to "break on all errors" and that causes it to break on invalid JSON strings.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Chi Chan
  • 11,890
  • 9
  • 34
  • 52
  • 5
    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
  • 8
    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
  • 24
    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
  • 35
    @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
  • Here's the **best** [answer](https://stackoverflow.com/a/20392392/8112776), but minified: `function isJsonString(json){try{var o=JSON.parse(json);if(o&&typeof o==="object"){return o}}catch(e){}return false}` ...,returns the parsed object, or else `False` if `json` is invalid. – ashleedawg Dec 02 '22 at 12:54

27 Answers27

1329

Use a JSON parser like JSON.parse:

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • 11
    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
  • 6
    @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
  • @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
  • 18
    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
  • 16
    @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
  • 1
    @Carcigenicate Totally agree. declare a variable outside the try catch then `varname = JSON.parse(jsonstr);` so you don't have to parse twice – Kellen Stuart Apr 04 '17 at 22:56
  • Using this is better as regex is usually slower. – Krishnadas PC Dec 23 '17 at 13:24
  • 2
    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
  • 7
    @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. – SwammiM 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
  • @Carcigenicate in that case put the `try`/`catch` in your code instead of putting that function in an `if` statement. – Boris Verkhovskiy Mar 16 '22 at 11:07
  • This will validate `{ a: 1, a: 2}` as valid. Any ideas to make this to validate false? – Alfonso Tienda Dec 02 '22 at 07:37
  • More specifically, you should catch the `SyntaxError` exception: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#exceptions – Raleigh L. Apr 13 '23 at 06:28
578

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:

/**
 * If you don't care about primitives and only objects then this function
 * is for you, otherwise look elsewhere.
 * This function will return `false` for any valid json primitive.
 * EG, 'true' -> false
 *     '123' -> false
 *     'null' -> false
 *     '"I'm a string"' -> false
 */
function tryParseJSONObject (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;
};
sparebytes
  • 12,546
  • 3
  • 21
  • 32
Matt H.
  • 10,438
  • 9
  • 45
  • 62
  • 15
    Of the answers on the page, this is the most robust and reliable. – Jonline May 30 '14 at 17:07
  • 41
    `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
  • 8
    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
  • 4
    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
  • 1
    @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
  • @sparebytes The function is just fine. I guess the author is looking for json strings that evaluate to objects and not just json values. In that case, returning `false` seems appropriate. – Ozichukwu Jul 22 '21 at 15:15
  • This doesn't make much sense quite honestly. Why would a false be returned but a boolean otherwise? – Jakub Keller Jun 28 '22 at 17:18
  • This will validate `{ a: 1, a: 2}` as valid. Any ideas to make this to validate false? – Alfonso Tienda Dec 02 '22 at 07:38
  • same function except compressed: `function isJsonString(json){try{var o=JSON.parse(json);if(o&&typeof o==="object"){return o}}catch(e){}return false}` – ashleedawg Dec 02 '22 at 12:52
  • "3 years late" and didn't read the OP does **not want try/catch** :) – serge Jan 18 '23 at 23:53
205

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
  • 27,717
  • 28
  • 128
  • 190
Mic
  • 24,812
  • 9
  • 57
  • 70
  • 70
    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
  • 15
    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
  • 2
    @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
  • 3
    @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
  • 10
    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
  • 3
    `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
  • 1
    If you absolutely cannot stomach a try/catch, there are several 3rd party JSON parsers available in NPM, and some of them do not throw when the supplied string is not valid. If you simply must avoid exceptions, use one of those. In no case should you try to write your own JSON validator, it's one step from [total madness](https://stackoverflow.com/a/1732454/26286). – Coderer Nov 12 '21 at 09:33
86
// 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;
}

// ES2015
var isAO = (val) => val instanceof Array || val instanceof Object;

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

LocalPCGuy
  • 6,006
  • 2
  • 32
  • 28
moeiscool
  • 1,318
  • 11
  • 14
43

Here my working code:

function IsJsonString(str) {
  try {
    var json = JSON.parse(str);
    return (typeof json === 'object');
  } catch (e) {
    return false;
  }
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
Anand Kumar
  • 477
  • 4
  • 2
37

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{
        var json = JSON.parse(text);
        return (typeof json === 'object');
    }
    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. :)

neteinstein
  • 17,529
  • 11
  • 93
  • 123
kukko
  • 643
  • 10
  • 21
  • 1
    JSON.parse(null), JSON.parse("false") doesn't throw errors, probably there are more examples – klodoma Mar 15 '18 at 10:18
  • 1
    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
  • This will validate `{ a: 1, a: 2}` as valid. Any ideas to make this to validate false? – Alfonso Tienda Dec 02 '22 at 07:38
21

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
  • 540
  • 1
  • 4
  • 12
  • 10
    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
9

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
  • 28,977
  • 24
  • 140
  • 219
8
  • 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;
    }

}

Jhamman Sharma
  • 147
  • 1
  • 2
7

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
  • 15,724
  • 11
  • 102
  • 146
  • 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
  • 1
    Word of warning for anyone planning to use this, not everything that is `true` from the above `isJSON` function will actually parse with `JSON.parse` successfully, the regexes don't fully test all possible strings. Examples of very simple truthy strings that would throw an error on JSON.parse: `'[' ']' '{' '}' '{"a"}'`. So just user beware, the try/catch method is likely safer for strings you don't control. – LocalPCGuy Mar 03 '23 at 23:45
7

I am way too late to the party. This is what I ended up doing. Using a quick regex pre-check improves performs by a big margin

if(/^\s*(\{|\[)/.test(str)){
    try{
        JSON.parse(str)
        // do something here, or return obj/true
    }catch(e){
        //  do nothing or return false
    }
}

The regex will check if string opens with a [ or {. This will eliminate most false cases (not all). Here is a quick performance test for you https://jsbench.me/awl6fgn8jb/1

Worst case this can be 10-15% slower than using try directly, worst case meaning all strings are valid json string.

Best case this is 99% faster than pure try, best case meaning all strings are non-valid json.

This only looks for strings that parse into objects or arrays. Note that stringified js-premitive values like "true" are valid JSON strings, I'm purposefully ignoring them for the sake of simplicity. For a comprehensive pre-check please add additional checks depending on your usecase.

Akash
  • 13,107
  • 1
  • 25
  • 19
  • 1
    This is the best answer that validates and parses in one routine. I would add an "else return false" for the initial if. Best answer ! – Thanasis Nov 25 '22 at 17:29
  • 1
    Some of "false positive" strings excluded by regex above: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#using_json.parse – LucianDex Apr 17 '23 at 17:44
5

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
  • 298
  • 1
  • 6
  • 18
5

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
  • 331
  • 4
  • 7
5

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

2
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
  • 678
  • 8
  • 13
  • 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
2

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
  • 87,898
  • 29
  • 167
  • 228
  • 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
  • 1
    @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
  • 1
    @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. – shreyasm-dev Jul 10 '20 at 15:57
2

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")
}
2

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
  • 950
  • 1
  • 12
  • 21
  • 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
2
if(resp) {
    try {
        resp = $.parseJSON(resp);
        console.log(resp);
    } catch(e) {
        alert(e);
    }
}

hope this works for you too

Darkcoder
  • 802
  • 1
  • 9
  • 17
2

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)
    }
  }
}
Eugene Blinn
  • 303
  • 2
  • 6
1

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,601
  • 19
  • 19
1

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
  • 696
  • 1
  • 5
  • 11
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
  • 422
  • 5
  • 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

eQ19
  • 9,880
  • 3
  • 65
  • 77
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
  • 20,682
  • 14
  • 97
  • 107
0

If you don't want to do try/catch anywhere, looking for a single liner, and don't mind using async functions:

const isJsonString = async str => ( await ((async v => JSON.parse(v))(str)).then(_ => true).catch(_ => false) );

await isJsonString('{ "Id": 1, "Name": "Coke" }'); // true
await isJsonString('foo'); // false
await isJsonString('<div>foo</div>'); // false
Arik
  • 5,266
  • 1
  • 27
  • 26
0

if you have a doubt the value is or not json

  function isStringified(jsonValue) { // use this function to check
   try {
    console.log("need to parse");
    return JSON.parse(jsonValue);
   } catch (err) {
    console.log("not need to parse");

     return jsonValue; 
    }
  }

and then

  const json = isStringified(stringValue);

  if (typeof json == "object") {
      console.log("string is a valid json")
    }else{
      console.log("string is not a valid json")
    }
Ateeb Asif
  • 94
  • 3
  • 2
    this is just wrong. If you try parse something what is not valid json it will throw exception, please remove your answer from here, so nobody try this – Jindřich Širůček Dec 15 '22 at 10:14
  • it is true it will throw an exception if it's not a valid json that's why i have added checks in it to make sure what we get is actually a valid json and i'm using this way in one of my project that's why i posted this answer. – Ateeb Asif Dec 16 '22 at 11:15
  • First provided code, which is not in try/catch block (const json = JSON.parse(string) ) will throw an exception and kill program and you will never get to to the typeof == "object" Try it in developers console – Jindřich Širůček Dec 17 '22 at 12:23
  • if you see here isStringified(stringValue); it is a function that is being called with some value inside the stringValue variable and when function starts to execute there is the try catch block that will either run successfully or catch any error and return accordingly after that it will reach the line typeof == "object". I tested this inside console and i'm using it in my project as well. – Ateeb Asif Mar 10 '23 at 15:51