开发者

How to check if a string is a valid JSON string?

开发者 https://www.devze.com 2023-01-16 06:52 出处:网络
isJsonString(\'{ "Id": 1, "Name": "Coke" }\') should be true and开发者_JAVA技巧
isJsonString('{ "Id": 1, "Name": "Coke" }')

should be true and

开发者_JAVA技巧
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.


Use a JSON parser like JSON.parse:

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}


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;
};


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 )


// 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.


Here my working code:

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


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. :)


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


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;
};


  • 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;
    }

}


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


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


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.


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.


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.


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


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.


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


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.


if(resp) {
    try {
        resp = $.parseJSON(resp);
        console.log(resp);
    } catch(e) {
        alert(e);
    }
}

hope this works for you too


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


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;

};


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}')


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


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
});


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.


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


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

精彩评论

暂无评论...
验证码 换一张
取 消