[javascript] How to test if a string is JSON or not?

I have a simple AJAX call, and the server will return either a JSON string with useful data or an error message string produced by the PHP function mysql_error(). How can I test whether this data is a JSON string or the error message.

It would be nice to use a function called isJSON just like you can use the function instanceof to test if something is an Array.

This is what I want:

if (isJSON(data)){
    //do some data stuff
}else{
    //report the error
    alert(data);
}

This question is related to javascript mysql json

The answer is


In addition to previous answers, in case of you need to validate a JSON format like "{}", you can use the following code:

const validateJSON = (str) => {
  try {
    const json = JSON.parse(str);
    if (Object.prototype.toString.call(json).slice(8,-1) !== 'Object') {
      return false;
    }
  } catch (e) {
    return false;
  }
  return true;
}

Examples of usage:

validateJSON('{}')
true
validateJSON('[]')
false
validateJSON('')
false
validateJSON('2134')
false
validateJSON('{ "Id": 1, "Name": "Coke" }')
true

I used this one (kind of mix of different answers, but anyway):

_x000D_
_x000D_
const isJSON = str => {_x000D_
  if (typeof str === 'string'){_x000D_
    try {_x000D_
      JSON.parse(str)_x000D_
      return true_x000D_
    } catch(e){_x000D_
    }_x000D_
  }_x000D_
  return false_x000D_
}_x000D_
_x000D_
_x000D_
_x000D_
[null, undefined, false, true, [], {}, _x000D_
 '', 'asdf', '{}', '[]', "{\"abc\": 2}","{\"abc\": \"2\"}"]_x000D_
  .map(el => {_x000D_
      console.log(`[>${el}<] - ${isJSON(el)}`)_x000D_
})_x000D_
_x000D_
console.log('-----------------')
_x000D_
_x000D_
_x000D_


This code is JSON.parse(1234) or JSON.parse(0) or JSON.parse(false) or JSON.parse(null) all will return true.

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

So I rewrote code in this way:

function isJson(item) {
    item = typeof item !== "string"
        ? JSON.stringify(item)
        : item;

    try {
        item = JSON.parse(item);
    } catch (e) {
        return false;
    }

    if (typeof item === "object" && item !== null) {
        return true;
    }

    return false;
}

Testing result:

isJson test result


Let's recap this (for 2019+).

Argument: Values such as true, false, null are valid JSON (?)

FACT: These primitive values are JSON-parsable but they are not well-formed JSON structures. JSON specification indicates JSON is built on on two structures: A collection of name/value pair (object) or an ordered list of values (array).

Argument: Exception handling shouldn't be used to do something expected.
(This is a comment that has 25+ upvotes!)

FACT: No! It's definitely legal to use try/catch, especially in a case like this. Otherwise, you'd need to do lots of string analysis stuff such as tokenizing / regex operations; which would have terrible performance.

hasJsonStructure()

This is useful if your goal is to check if some data/text has proper JSON interchange format.

function hasJsonStructure(str) {
    if (typeof str !== 'string') return false;
    try {
        const result = JSON.parse(str);
        const type = Object.prototype.toString.call(result);
        return type === '[object Object]' 
            || type === '[object Array]';
    } catch (err) {
        return false;
    }
}

Usage:

hasJsonStructure('true')             // —» false
hasJsonStructure('{"x":true}')       // —» true
hasJsonStructure('[1, false, null]') // —» true

safeJsonParse()

And this is useful if you want to be careful when parsing some data to a JavaScript value.

function safeJsonParse(str) {
    try {
        return [null, JSON.parse(str)];
    } catch (err) {
        return [err];
    }
}

Usage:

const [err, result] = safeJsonParse('[Invalid JSON}');
if (err) {
    console.log('Failed to parse JSON: ' + err.message);
} else {
    console.log(result);
}

Well... It depends the way you are receiving your data. I think the server is responding with a JSON formated string (using json_encode() in PHP,e.g.). If you're using JQuery post and set response data to be a JSON format and it is a malformed JSON, this will produce an error:

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        //Supposing x is a JSON property...
        alert(response.x);

  },
  dataType: 'json',
  //Invalid JSON
  error: function (){ alert("error!"); }
});

But, if you're using the type response as text, you need use $.parseJSON. According jquery site: "Passing in a malformed JSON string may result in an exception being thrown". Thus your code will be:

$.ajax({
  type: 'POST',
  url: 'test2.php',
  data: "data",
  success: function (response){

        try {
            parsedData = JSON.parse(response);
        } catch (e) {
            // is not a valid JSON string
        }

  },
  dataType: 'text',
});

var parsedData;

try {
    parsedData = JSON.parse(data)
} catch (e) {
    // is not a valid JSON string
}

However, I will suggest to you that your http call / service should return always a data in the same format. So if you have an error, than you should have a JSON object that wrap this error:

{"error" : { "code" : 123, "message" : "Foo not supported" } } 

And maybe use as well as HTTP status a 5xx code.


There are probably tests you can do, for instance if you know that the JSON returned is always going to be surrounded by { and } then you could test for those characters, or some other hacky method. Or you could use the json.org JS library to try and parse it and test if it succeeds.

I would however suggest a different approach. Your PHP script currently returns JSON if the call is successful, but something else if it is not. Why not always return JSON?

E.g.

Successful call:

{ "status": "success", "data": [ <your data here> ] }

Erroneous call:

{ "status": "error", "error": "Database not found" }

This would make writing your client side JS much easier - all you have to do is check the "status" member and the act accordingly.


when using jQuery $.ajax() the response will have the responseJSON property if the response was JSON, this could be checked like this:

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

Warning: For methods relying on JSON.parse - Arrays and quote surrounded strings will pass too (ie. console.log(JSON.parse('[3]'), JSON.parse('"\uD800"')))

To avoid all non-object JSON primitives (boolean, null, array, number, string), I suggest using the following:

/* Validate a possible object ie. o = { "a": 2 } */
const isJSONObject = (o) => 
  !!o && (typeof o === 'object') && !Array.isArray(o) && 
  (() => { try { return Boolean(JSON.stringify(o)); } catch { return false } })()

/* Validate a possible JSON object represented as string ie. s = '{ "a": 3 }' */
function isJSONObjectString(s) {
    try {
        const o = JSON.parse(s);
        return !!o && (typeof o === 'object') && !Array.isArray(o)
    } catch {
        return false
    }
}

Code Explanation

  • !!o - Not falsy (excludes null, which registers as typeof 'object')
  • (typeof o === 'object') - Excludes boolean, number, and string
  • !Array.isArray(o) - Exclude arrays (which register as typeof 'object')
  • try ... JSON.stringify / JSON.parse - Asks JavaScript engine to determine if valid JSON

Why not use the hasJsonStructure() answer?

Relying on toString() is not a good idea. This is because different JavaScript Engines may return a different string representation. In general, methods which rely on this may fail in different environments or may be subject to fail later should the engine ever change the string result

Why is catching an exception not a hack?

It was brought up that catching an exception to determine something's validity is never the right way to go. This is generally good advice, but not always. In this case, exception catching is likely is the best route because it relies on the JavaScript engine's implementation of validating JSON data.

Relying on the JS engine offers the following advantages:

  1. More thorough and continually up-to-date as JSON spec changes
  2. Likely to run faster (as it's lower level code)

When given the opportunity to lean on the JavaScript engine, I'd suggest doing it. Particularly so in this case. Although it may feel hacky to catch an exception, you're really just handling two possible return states from an external method.


All json strings start with '{' or '[' and end with the corresponding '}' or ']', so just check for that.

Here's how Angular.js does it:

var JSON_START = /^\[|^\{(?!\{)/;
var JSON_ENDS = {
  '[': /]$/,
  '{': /}$/
};

function isJsonLike(str) {
    var jsonStart = str.match(JSON_START);
    return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
}

https://github.com/angular/angular.js/blob/v1.6.x/src/ng/http.js


I use just 2 lines to perform that:

var isValidJSON = true;
try { JSON.parse(jsonString) } catch { isValidJSON = false }

That's all!

But keep in mind there are 2 traps:
1. JSON.parse(null) returns null
2. Any number or string can be parsed with JSON.parse() method.
   JSON.parse("5") returns 5
   JSON.parse(5) returns 5

Let's some play on code:

// TEST 1
var data = '{ "a": 1 }'

// Avoiding 'null' trap! Null is confirmed as JSON.
var isValidJSON = data ? true : false
try { JSON.parse(data) } catch(e) { isValidJSON = false }

console.log("data isValidJSON: ", isValidJSON);
console.log("data isJSONArray: ", isValidJSON && JSON.parse(data).length ? true : false);

Console outputs:
data isValidJSON:  true
data isJSONArray:  false


// TEST 2
var data2 = '[{ "b": 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data2) } catch(e) { isValidJSON = false }

console.log("data2 isValidJSON: ", isValidJSON);
console.log("data2 isJSONArray: ", isValidJSON && JSON.parse(data2).length ? true : false);

Console outputs:
data2 isValidJSON:  true
data2 isJSONArray:  true


// TEST 3
var data3 = '[{ 2 }]'

var isValidJSON = data ? true : false
try { JSON.parse(data3) } catch(e) { isValidJSON = false }

console.log("data3 isValidJSON: ", isValidJSON);
console.log("data3 isJSONArray: ", isValidJSON && JSON.parse(data3).length ? true : false);

Console outputs:
data3 isValidJSON:  false
data3 isJSONArray:  false


// TEST 4
var data4 = '2'

var isValidJSON = data ? true : false
try { JSON.parse(data4) } catch(e) { isValidJSON = false }

console.log("data4 isValidJSON: ", isValidJSON);
console.log("data4 isJSONArray: ", isValidJSON && JSON.parse(data4).length ? true : false);


Console outputs:
data4 isValidJSON:  true
data4 isJSONArray:  false


// TEST 5
var data5 = ''

var isValidJSON = data ? true : false
try { JSON.parse(data5) } catch(e) { isValidJSON = false }

console.log("data5 isValidJSON: ", isValidJSON);
console.log("data5 isJSONArray: ", isValidJSON && JSON.parse(data5).length ? true : false);


Console outputs:
data5 isValidJSON:  false
data5 isJSONArray:  false

// TEST 6
var data6; // undefined

var isValidJSON = data ? true : false
try { JSON.parse(data6) } catch(e) { isValidJSON = false }

console.log("data6 isValidJSON: ", isValidJSON);
console.log("data6 isJSONArray: ", isValidJSON && JSON.parse(data6).length ? true : false);

Console outputs:
data6 isValidJSON:  false
data6 isJSONArray:  false

If the server is responding with JSON then it would have an application/json content-type, if it is responding with a plain text message then it should have a text/plain content-type. Make sure the server is responding with the correct content-type and test that.


You could try decoding it and catching the exception (native or json2.js):

try {
  newObj = JSON.parse(myJsonString);
} catch (e) {
  console.log('Not JSON');
}

However, I would suggest making the response always be valid JSON. If you get an error back from your MySQL query, simply send back JSON with the error:

{"error":"The MySQL error string."}

And then:

if (myParsedJSON.error) {
  console.log('An error occurred: ' + myParsedJSON.error);
}

I like best answer but if it is an empty string it returns true. So here's a fix:

function isJSON(MyTestStr){
    try {
        var MyJSON = JSON.stringify(MyTestStr);
        var json = JSON.parse(MyJSON);
        if(typeof(MyTestStr) == 'string')
            if(MyTestStr.length == 0)
                return false;
    }
    catch(e){
        return false;
    }
    return true;
}

You can try the following one because it also validates number, null, string but the above-marked answer is not working correctly it's just a fix of the above function:

function isJson(str) {
  try {
      const obj = JSON.parse(str);
      if (obj && typeof obj === `object`) {
        return true;
      }
    } catch (err) {
      return false;
    }
   return false;
}

Here is a code with some minor modification in Bourne's answer. As JSON.parse(number) works fine without any exception so added isNaN.

function isJson(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return isNaN(str);
}

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to mysql

Implement specialization in ER diagram How to post query parameters with Axios? PHP with MySQL 8.0+ error: The server requested authentication method unknown to the client Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver' phpMyAdmin - Error > Incorrect format parameter? Authentication plugin 'caching_sha2_password' is not supported How to resolve Unable to load authentication plugin 'caching_sha2_password' issue Connection Java-MySql : Public Key Retrieval is not allowed How to grant all privileges to root user in MySQL 8.0 MySQL 8.0 - Client does not support authentication protocol requested by server; consider upgrading MySQL client

Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.?