Fastest way to check if a string is JSON in PHP?

PhpJsonError HandlingJson DeserializationJsonresult

Php Problem Overview


I need a really, really fast method of checking if a string is JSON or not. I feel like this is not the best way:

function isJson($string) {
    return ((is_string($string) &&
            (is_object(json_decode($string)) ||
            is_array(json_decode($string))))) ? true : false;
}

Any performance enthusiasts out there want to improve this method?

Php Solutions


Solution 1 - Php

function isJson($string) {
   json_decode($string);
   return json_last_error() === JSON_ERROR_NONE;
}

Solution 2 - Php

> Answer to the Question

The function json_last_error returns the last error occurred during the JSON encoding and decoding. So the fastest way to check the valid JSON is

// decode the JSON data
// set second parameter boolean TRUE for associative array output.
$result = json_decode($json);

if (json_last_error() === JSON_ERROR_NONE) {
	// JSON is valid
}

// OR this is equivalent

if (json_last_error() === 0) {
	// JSON is valid
}

Note that json_last_error is supported in PHP >= 5.3.0 only.

> Full program to check the exact ERROR

It is always good to know the exact error during the development time. Here is full program to check the exact error based on PHP docs.

function json_validate($string)
{
	// decode the JSON data
	$result = json_decode($string);

	// switch and check possible JSON errors
	switch (json_last_error()) {
		case JSON_ERROR_NONE:
			$error = ''; // JSON is valid // No error has occurred
			break;
		case JSON_ERROR_DEPTH:
			$error = 'The maximum stack depth has been exceeded.';
			break;
		case JSON_ERROR_STATE_MISMATCH:
			$error = 'Invalid or malformed JSON.';
			break;
		case JSON_ERROR_CTRL_CHAR:
			$error = 'Control character error, possibly incorrectly encoded.';
			break;
		case JSON_ERROR_SYNTAX:
			$error = 'Syntax error, malformed JSON.';
			break;
		// PHP >= 5.3.3
		case JSON_ERROR_UTF8:
			$error = 'Malformed UTF-8 characters, possibly incorrectly encoded.';
			break;
		// PHP >= 5.5.0
		case JSON_ERROR_RECURSION:
			$error = 'One or more recursive references in the value to be encoded.';
			break;
		// PHP >= 5.5.0
		case JSON_ERROR_INF_OR_NAN:
			$error = 'One or more NAN or INF values in the value to be encoded.';
			break;
		case JSON_ERROR_UNSUPPORTED_TYPE:
			$error = 'A value of a type that cannot be encoded was given.';
			break;
		default:
			$error = 'Unknown JSON error occured.';
			break;
	}

	if ($error !== '') {
		// throw the Exception or exit // or whatever :)
		exit($error);
	}

	// everything is OK
	return $result;
}

> Testing with Valid JSON INPUT

$json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
$output = json_validate($json);
print_r($output);

> Valid OUTPUT

Array
(
	[0] => stdClass Object
		(
			[user_id] => 13
			[username] => stack
		)

	[1] => stdClass Object
		(
			[user_id] => 14
			[username] => over
		)
)

> Testing with invalid JSON

$json = '{background-color:yellow;color:#000;padding:10px;width:650px;}';
$output = json_validate($json);
print_r($output);

> Invalid OUTPUT

Syntax error, malformed JSON.

> Extra note for (PHP >= 5.2 && PHP < 5.3.0)

Since json_last_error is not supported in PHP 5.2, you can check if the encoding or decoding returns boolean FALSE. Here is an example

// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
    // JSON is invalid
}

Solution 3 - Php

All you really need to do is this...

if (is_object(json_decode($MyJSONArray))) 
{ 
    ... do something ...
}

This request does not require a separate function even. Just wrap is_object around json_decode and move on. Seems this solution has people putting way too much thought into it.

Solution 4 - Php

Using json_decode to "probe" it might not actually be the fastest way. If it's a deeply nested structure, then instantiating a lot of objects of arrays to just throw them away is a waste of memory and time.

So it might be faster to use preg_match and the RFC4627 regex to also ensure validity:

  // in JS:
  var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
         text.replace(/"(\\.|[^"\\])*"/g, '')));

The same in PHP:

  return !preg_match('/[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]/',
       preg_replace('/"(\\.|[^"\\\\])*"/', '', $json_string));

Not enough of a performance enthusiast to bother with benchmarks here however.

Solution 5 - Php

This will return true if your string represents a json array or object:

function isJson($str) {
    $json = json_decode($str);
    return $json && $str != $json;
}

It rejects json strings that only contains a number, string or boolean, although those strings are technically valid json.

var_dump(isJson('{"a":5}')); // bool(true)
var_dump(isJson('[1,2,3]')); // bool(true)
var_dump(isJson('1')); // bool(false)
var_dump(isJson('1.5')); // bool(false)
var_dump(isJson('true')); // bool(false)
var_dump(isJson('false')); // bool(false)
var_dump(isJson('null')); // bool(false)
var_dump(isJson('hello')); // bool(false)
var_dump(isJson('')); // bool(false)

It is the shortest way I can come up with.

Solution 6 - Php

The simplest and fastest way that I use is following;

$json_array = json_decode( $raw_json , true );

if( $json_array == NULL )   //check if it was invalid json string
    die ('Invalid');  // Invalid JSON error

 // you can execute some else condition over here in case of valid JSON

It is because json_decode() returns NULL if the entered string is not json or invalid json.


Simple function to validate JSON

If you have to validate your JSON in multiple places, you can always use the following function.

function is_valid_json( $raw_json ){
    return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}

In the above function, you will get true in return if it is a valid JSON.

Solution 7 - Php

function is_json($str){ 
    return json_decode($str) != null;
}

http://tr.php.net/manual/en/function.json-decode.php return value is null when invalid encoding detected.

Solution 8 - Php

I found this question after coming across something similar in my work, yesterday. My solution in the end was a hybrid of some of the approaches above:

function is_JSON($string) {

    return (is_null(json_decode($string))) ? FALSE : TRUE;
}

Solution 9 - Php

You must validate your input to make sure the string you pass is not empty and is, in fact, a string. An empty string is not valid JSON.

function is_json($string) {
  return !empty($string) && is_string($string) && is_array(json_decode($string, true)) && json_last_error() == 0;
}

I think in PHP it's more important to determine if the JSON object even has data, because to use the data you will need to call json_encode() or json_decode(). I suggest denying empty JSON objects so you aren't unnecessarily running encodes and decodes on empty data.

function has_json_data($string) {
  $array = json_decode($string, true);
  return !empty($string) && is_string($string) && is_array($array) && !empty($array) && json_last_error() == 0;
}

Solution 10 - Php

The fastest way is to "maybe decode" the possible JSON string

Is this really the fastest method?

If you want to decode complex objects or larger arrays, this is the fastest solution! Besides being fast, this is the only solution that can reliably handle any kind of input value - other functions throw errors or return incorrect results in some cases.

If your JSON string contains short values (e.g., strings, numbers or objects with only 1-2 attributes) then all solutions in this SO questions come to a similar performance.

Here's a quick overview with comparison - you can find the test-cases in the linked gist. The last column uses the code from this answer:

PHP version: 7.4.21

test1: json_last_error() == JSON_ERROR_NONE
test2: is_object( json_decode() )
test3: json_decode() && $res != $string
test4: preg_match()
test5: "maybe decode" approach

      | test1    | test2    | test3    | test4    | test5    
   #0 | 0.0147   | 0.0109 ✓︎ | 0.0119   | 0.0177   | 0.0194   
   #1 | 0.0129   | 0.0106   | 0.0098   | - INV -  | 0.0078 ✓︎ 
   #2 | 0.0076   | 0.0075   | 0.0063 ✓︎ | 0.0083   | 0.0133   
   #3 | 0.0126   | 0.0105   | 0.0096 ✓︎ | - INV -  | 0.0172   
   #4 | 0.0070   | - INV -  | 0.0061 ✓︎ | 0.0141   | 0.0134   
   #5 | 0.0114   | - INV -  | 0.0101   | 0.0075 ✓︎ | 0.0168   
   #6 | 0.0203   | - INV -  | 0.0195   | 0.0073 ✓︎ | 0.0259   
   #7 | 0.0046   | - INV -  | - INV -  | 0.0077   | 0.0031 ✓︎ 
   #8 | 0.0066   | - INV -  | - INV -  | 0.0081   | 0.0020 ✓︎ 
   #9 | 1.0781   | - INV -  | 1.0555   | 0.0998 ✓︎ | 1.0385   
  #10 | 0.3183 ✓︎ | 0.3246   | 0.3270   | 1.0186   | 0.3311   
  #11 | 0.0071   | 0.0068   | 0.0067 ✓︎ | - INV -  | 0.0079   
  #12 | - ERR -  | - ERR -  | - ERR -  | - ERR -  | 0.0025 ✓︎ 
  #13 | - ERR -  | - ERR -  | - ERR -  | - ERR -  | 0.0024 ✓︎ 
  Avg | 0.1251   | 0.0618 ✓︎ | 0.1463   | 0.1321   | 0.1072

Note that the fastest solution produces the most incorrect results. From all other solutions, the "maybe decode" approach is not only the fastest, but also the only solution with correct results.

Here is the full performance comparison script, there you can see the test-data I used for the comparison: https://gist.github.com/stracker-phil/6a80e6faedea8dab090b4bf6668ee461


The "maybe decode" logic/code

We first perform some type checks and string comparisons before attempting to decode the JSON string. This gives us the best performance because json_decode() can be slow.

/**
 * Returns true, when the given parameter is a valid JSON string.
 */
function is_json( $value ) {
	// Numeric strings are always valid JSON.
	if ( is_numeric( $value ) ) { return true; }

	// A non-string value can never be a JSON string.
	if ( ! is_string( $value ) ) { return false; }

	// Any non-numeric JSON string must be longer than 2 characters.
	if ( strlen( $value ) < 2 ) { return false; }

	// "null" is valid JSON string.
	if ( 'null' === $value ) { return true; }

	// "true" and "false" are valid JSON strings.
	if ( 'true' === $value ) { return true; }
	if ( 'false' === $value ) { return false; }

	// Any other JSON string has to be wrapped in {}, [] or "".
	if ( '{' != $value[0] && '[' != $value[0] && '"' != $value[0] ) { return false; }

    // Verify that the trailing character matches the first character.
    $last_char = $value[strlen($value) -1];
    if ( '{' == $value[0] && '}' != $last_char ) { return false; }
    if ( '[' == $value[0] && ']' != $last_char ) { return false; }
    if ( '"' == $value[0] && '"' != $last_char ) { return false; }

    // See if the string contents are valid JSON.
    return null !== json_decode( $value );
}

Extra: Use this logic to safely double-decode JSON

This function uses the same logic but either returns the decoded JSON object or the original value.

I use this function in a parser that recursively decodes a complex object. Some attributes might be decoded already by an earlier iteration. That function recognizes this and does not attempt to double decode the value again.

/**
 * Tests, if the given $value parameter is a JSON string.
 * When it is a valid JSON value, the decoded value is returned.
 * When the value is no JSON value (i.e. it was decoded already), then 
 * the original value is returned.
 */
function get_data( $value, $as_object = false ) {
	if ( is_numeric( $value ) ) { return 0 + $value; }
	if ( ! is_string( $value ) ) { return $value; }
	if ( strlen( $value ) < 2 ) { return $value; }
	if ( 'null' === $value ) { return null; }
	if ( 'true' === $value ) { return true; }
	if ( 'false' === $value ) { return false; }
	if ( '{' != $value[0] && '[' != $value[0] && '"' != $value[0] ) { return $value; }

	$json_data = json_decode( $value, $as_object );
	if ( is_null( $json_data ) ) { return $value; }
	return $json_data;
}

Note: When passing a non-string to any of the other solution in this SO question, you will get dramatically degraded performance + wrong return values (or even fatal errors). This code is bulletproof and highly performant.

Solution 11 - Php

This will do it:

function isJson($string) {
    $decoded = json_decode($string); // decode our JSON string
    if ( !is_object($decoded) && !is_array($decoded) ) {
        /*
        If our string doesn't produce an object or array
        it's invalid, so we should return false
        */
        return false;
    }
    /*
    If the following line resolves to true, then there was
    no error and our JSON is valid, so we return true.
    Otherwise it isn't, so we return false.
    */
    return (json_last_error() == JSON_ERROR_NONE);
}

if ( isJson($someJsonString) ) {
    echo "valid JSON";
} else {
    echo "not valid JSON";
}

As shown in other answers, json_last_error() returns any error from our last json_decode(). However there are some edge use cases where this function alone is not comprehensive enough. For example, if you json_decode() an integer (eg: 123), or a string of numbers with no spaces or other characters (eg: "123"), the json_last_error() function will not catch an error.

To combat this, I've added an extra step that ensures the result of our json_decode() is either an object or an array. If it's not, then we return false.

To see this in action, check these two examples:

Solution 12 - Php

Using PHPBench with the following class, the below results were achieved:

<?php

declare(strict_types=1);

/**
 * @Revs(1000)
 * @Iterations(100)
 */
class BenchmarkJson
{
    public function benchCatchValid(): bool
    {
        $validJson = '{"validJson":true}';
        try {
            json_decode($validJson, true, 512, JSON_THROW_ON_ERROR);
            return true;
        } catch(\JsonException $exception) {}
        return false;
    }

    public function benchCatchInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        try {
            json_decode($invalidJson, true, 512, JSON_THROW_ON_ERROR);
            return true;
        } catch(\JsonException $exception) {}
        return false;
    }

    public function benchLastErrorValid(): bool
    {
        $validJson = '{"validJson":true}';
        json_decode($validJson, true);
        return (json_last_error() === JSON_ERROR_NONE);
    }

    public function benchLastErrorInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        json_decode($invalidJson, true);
        return (json_last_error() === JSON_ERROR_NONE);
    }

    public function benchNullValid(): bool
    {
        $validJson = '{"validJson":true}';
        return (json_decode($validJson, true) !== null);
    }

    public function benchNullInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        return (json_decode($invalidJson, true) !== null);
    }
}

6 subjects, 600 iterations, 6,000 revs, 0 rejects, 0 failures, 0 warnings
(best [mean mode] worst) = 0.714 [1.203 1.175] 1.073 (μs)
⅀T: 721.504μs μSD/r 0.089μs μRSD/r: 7.270%
suite: 1343ab9a3590de6065bc0bc6eeb344c9f6eba642, date: 2020-01-21, stime: 12:50:14
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| benchmark     | subject               | set | revs | its | mem_peak   | best    | mean    | mode    | worst   | stdev   | rstdev | diff  |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| BenchmarkJson | benchCatchValid       | 0   | 1000 | 100 | 2,980,168b | 0.954μs | 1.032μs | 1.016μs | 1.428μs | 0.062μs | 6.04%  | 1.33x |
| BenchmarkJson | benchCatchInvalid     | 0   | 1000 | 100 | 2,980,184b | 2.033μs | 2.228μs | 2.166μs | 3.001μs | 0.168μs | 7.55%  | 2.88x |
| BenchmarkJson | benchLastErrorValid   | 0   | 1000 | 100 | 2,980,184b | 1.076μs | 1.195μs | 1.169μs | 1.616μs | 0.083μs | 6.97%  | 1.54x |
| BenchmarkJson | benchLastErrorInvalid | 0   | 1000 | 100 | 2,980,184b | 0.785μs | 0.861μs | 0.863μs | 1.132μs | 0.056μs | 6.54%  | 1.11x |
| BenchmarkJson | benchNullValid        | 0   | 1000 | 100 | 2,980,168b | 0.985μs | 1.124μs | 1.077μs | 1.731μs | 0.114μs | 10.15% | 1.45x |
| BenchmarkJson | benchNullInvalid      | 0   | 1000 | 100 | 2,980,184b | 0.714μs | 0.775μs | 0.759μs | 1.073μs | 0.049μs | 6.36%  | 1.00x |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+

Conclusion: The fastest way to check if json is valid is to return json_decode($json, true) !== null).

Solution 13 - Php

Easy method is to check the json result..

$result = @json_decode($json,true);
	if (is_array($result)) {
		echo 'JSON is valid';
	}else{
		echo 'JSON is not valid';
	}

Solution 14 - Php

in GuzzleHttp:

/**
 * Wrapper for json_decode that throws when an error occurs.
 *
 * @param string $json    JSON data to parse
 * @param bool $assoc     When true, returned objects will be converted
 *                        into associative arrays.
 * @param int    $depth   User specified recursion depth.
 * @param int    $options Bitmask of JSON decode options.
 *
 * @return mixed
 * @throws \InvalidArgumentException if the JSON cannot be decoded.
 * @link http://www.php.net/manual/en/function.json-decode.php
 */
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
{
    $data = \json_decode($json, $assoc, $depth, $options);
    if (JSON_ERROR_NONE !== json_last_error()) {
        throw new \InvalidArgumentException(
            'json_decode error: ' . json_last_error_msg());
    }

    return $data;
}

/**
 * Wrapper for JSON encoding that throws when an error occurs.
 *
 * @param mixed $value   The value being encoded
 * @param int    $options JSON encode option bitmask
 * @param int    $depth   Set the maximum depth. Must be greater than zero.
 *
 * @return string
 * @throws \InvalidArgumentException if the JSON cannot be encoded.
 * @link http://www.php.net/manual/en/function.json-encode.php
 */
function json_encode($value, $options = 0, $depth = 512)
{
    $json = \json_encode($value, $options, $depth);
    if (JSON_ERROR_NONE !== json_last_error()) {
        throw new \InvalidArgumentException(
            'json_encode error: ' . json_last_error_msg());
    }

    return $json;
}

Solution 15 - Php

//Tested thoroughly, Should do the job:
public static function is_json(string $json):bool
{
    json_decode($json);
    if (json_last_error() === JSON_ERROR_NONE) {
	    return true;
    }
    return false;
}

Solution 16 - Php

Earlier i was just checking for a null value, which was wrong actually.

    $data = "ahad";
    $r_data = json_decode($data);
    if($r_data){//json_decode will return null, which is the behavior we expect
        //success
    }

The above piece of code works fine with strings. However as soon as i provide number, it breaks up.for example.

    $data = "1213145";
    $r_data = json_decode($data);

    if($r_data){//json_decode will return 1213145, which is the behavior we don't expect
        //success
    }

To fix it what i did was very simple.

    $data = "ahad";
    $r_data = json_decode($data);

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";

Solution 17 - Php

We need to check if passed string is not numeric because in this case json_decode raises no error.

function isJson($str) {
    $result = false;
    if (!preg_match("/^\d+$/", trim($str))) {
        json_decode($str);
        $result = (json_last_error() == JSON_ERROR_NONE);
    }

    return $result;
}

Solution 18 - Php

Another simple way

function is_json($str)
{
	return is_array(json_decode($str,true));
}

Solution 19 - Php

I've tried some of those solution but nothing was working for me. I try this simple thing :

$isJson = json_decode($myJSON);

if ($isJson instanceof \stdClass || is_array($isJson)) {
   echo("it's JSON confirmed");
} else {
   echo("nope");
}

I think it's a fine solutiuon since JSON decode without the second parameter give an object.

EDIT : If you know what will be the input, you can adapt this code to your needs. In my case I know I have a Json wich begin by "{", so i don't need to check if it's an array.

Solution 20 - Php

Should be something like this:

 function isJson($string)
 {
    // 1. Speed up the checking & prevent exception throw when non string is passed
    if (is_numeric($string) ||
        !is_string($string) ||
        !$string) {
        return false;
    }

    $cleaned_str = trim($string);
    if (!$cleaned_str || !in_array($cleaned_str[0], ['{', '['])) {
        return false;
    }
    
    // 2. Actual checking
    $str = json_decode($string);
    return (json_last_error() == JSON_ERROR_NONE) && $str && $str != $string;
}

UnitTest

public function testIsJson()
{
    $non_json_values = [
        "12",
        0,
        1,
        12,
        -1,
        '',
        null,
        0.1,
        '.',
        "''",
        true,
        false,
        [],
        '""',
        '[]',
        '   {',
        '   [',
    ];

   $json_values = [
        '{}',
        '{"foo": "bar"}',
        '[{}]',
        '  {}',
        ' {}  '
    ];

   foreach ($non_json_values as $non_json_value) {
        $is_json = isJson($non_json_value);
        $this->assertFalse($is_json);
    }

    foreach ($json_values as $json_value) {
        $is_json = isJson($json_value);
        $this->assertTrue($is_json);
    }
}

Solution 21 - Php

Hi here's a little snippet from my library, in this first condition I'm just checking if the data is json then return it if correctly decoded, please note the substr usage for performance ( I haven't seen yet any json file not begining neither by { or [

$input=trim($input);
if ((substr($input, 0, 1) == '{' && substr($input, -1) == '}') or (substr($input, 0, 1) == '[' && substr($input, -1) == ']')) {
    $output = json_decode($input, 1);
    if (in_array(gettype($output),['object','array'])) {
        #then it's definitely JSON
    }
}

Solution 22 - Php

I don't know about performance or elegance of my solution, but it's what I'm using:

if (preg_match('/^[\[\{]\"/', $string)) {
    $aJson = json_decode($string, true);
    if (!is_null($aJson)) {
       ... do stuff here ...
    }
}

Since all my JSON encoded strings start with {" it suffices to test for this with a RegEx. I'm not at all fluent with RegEx, so there might be a better way to do this. Also: strpos() might be quicker.

Just trying to give in my tuppence worth.

P.S. Just updated the RegEx string to /^[\[\{]\"/ to also find JSON array strings. So it now looks for either [" or {" at the beginning of the string.

Solution 23 - Php

function isJson($string) {
    $obj = json_decode($string);
    return json_last_error() === JSON_ERROR_NONE && gettype($obj ) == "object";
}

this works and doesn't return true for numbers

new update

The above solution does not have good performance if the JSON is long and you don't need to use $obj

if you just want check, it's better to use below function

function isJson($string) {
    if(is_numeric($string)) return false;
    json_decode($string);
    return json_last_error() === JSON_ERROR_NONE;
}

Solution 24 - Php

Expanding on this answer How about the following:

<?php

    $json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
    //$json = '12';

    function isJson($string) {
        json_decode($string);
        if(json_last_error() == JSON_ERROR_NONE) {
            if(substr($string,0,1) == '[' && substr($string,-1) == ']') { return TRUE; }
            else if(substr($string,0,1) == '{' && substr($string,-1) == '}') { return TRUE; }
            else { return FALSE; }
        }
    }

    echo isJson($json);
?>

Solution 25 - Php

Another suggestion from me :)

function isJson(string $string) {
  return ($result = json_decode($string, true)) ? $result : $string;
}

Solution 26 - Php

This is what I recommend

if (!in_array(substr($string, 0, 1), ['{', '[']) || !in_array(substr($string, -1), ['}', ']'])) {
  return false;
} else {
  json_decode($string);
  return (json_last_error() === JSON_ERROR_NONE);
}

Solution 27 - Php

$r = (array)json_decode($arr);
if(!is_array($r) || count($r) < 1) return false;

Solution 28 - Php

If a local file stations.json is invalid, missing, or is more than one month old, do something.

if (!is_array(json_decode(@file_get_contents("stations.json"))) || time() > filemtime("stations.json") + (60*60*24*31)){
  // The json file is invalid, missing, or is more than 1 month old
  // Get a fresh version
} else {
  // Up to date
}

Solution 29 - Php

Freshly-made function for PHP 5.2 compatibility, if you need the decoded data on success:

function try_json_decode( $json, & $success = null ){
  // non-strings may cause warnings
  if( !is_string( $json )){
    $success = false;
    return $json;
  }

  $data = json_decode( $json );

  // output arg
  $success =

    // non-null data: success!
    $data !==  null  ||

    // null data from 'null' json: success!
    $json === 'null' ||

    // null data from '  null  ' json padded with whitespaces: success!
    preg_match('/^\s*null\s*$/', $json );

  // return decoded or original data
  return $success ? $data : $json;
}

Usage:

$json_or_not = ...;

$data = try_json_decode( $json_or_not, $success );

if( $success )
     process_data( $data );
else what_the_hell_is_it( $data );

Some tests:

var_dump( try_json_decode( array(), $success ), $success );
// ret = array(0){}, $success == bool(false)

var_dump( try_json_decode( 123, $success ), $success );
// ret = int(123), $success == bool(false)

var_dump( try_json_decode('      ', $success ), $success );
// ret = string(6) "      ", $success == bool(false)

var_dump( try_json_decode( null, $success ), $success );
// ret = NULL, $success == bool(false)

var_dump( try_json_decode('null', $success ), $success );
// ret = NULL, $success == bool(true)

var_dump( try_json_decode('  null  ', $success ), $success );
// ret = NULL, $success == bool(true)

var_dump( try_json_decode('  true  ', $success ), $success );
// ret = bool(true), $success == bool(true)

var_dump( try_json_decode('  "hello"  ', $success ), $success );
// ret = string(5) "hello", $success == bool(true)

var_dump( try_json_decode('  {"a":123}  ', $success ), $success );
// ret = object(stdClass)#2 (1) { ["a"]=> int(123) }, $success == bool(true)

Solution 30 - Php

function is_json($input) {
    
    $input = trim($input);
    
    if (substr($input,0,1)!='{' OR substr($input,-1,1)!='}')
        return false;

    return is_array(@json_decode($input, true));
}

Solution 31 - Php

A simple modification to henrik's answer to touch most required possibilities. ( including " {} and [] " )

function isValidJson($string) {
    json_decode($string);
    if(json_last_error() == JSON_ERROR_NONE) {
        
        if( $string[0] == "{" || $string[0] == "[" ) { 
            $first = $string [0];
            
            if( substr($string, -1) == "}" || substr($string, -1) == "]" ) {
                $last = substr($string, -1);
                
                if($first == "{" && $last == "}"){
                    return true;
                }
                
                if($first == "[" && $last == "]"){
                    return true;
                }
                
                return false;
                
            }
            return false;
        }
        
        return false;
    }
   
    return false;
    
}

Solution 32 - Php

Here's a performant and simple function I created (which uses basic string validation before using json_decode for larger strings):

function isJson($string) {
	$response = false;

	if (
		is_string($string) &&
		($string = trim($string)) &&
		($stringLength = strlen($string)) &&
		(
			(
				stripos($string, '{') === 0 &&
				(stripos($string, '}', -1) + 1) === $stringLength
			) ||
			(
				stripos($string, '[{') === 0 &&
				(stripos($string, '}]', -1) + 2) === $stringLength
			)
		) &&
		($decodedString = json_decode($string, true)) &&
		is_array($decodedString)
	) {
		$response = true;
	}

	return $response;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKirk OuimetView Question on Stackoverflow
Solution 1 - PhpHenrik P. HesselView Answer on Stackoverflow
Solution 2 - PhpMadan SapkotaView Answer on Stackoverflow
Solution 3 - Phpuser1653711View Answer on Stackoverflow
Solution 4 - PhpmarioView Answer on Stackoverflow
Solution 5 - PhpCyrilView Answer on Stackoverflow
Solution 6 - PhpMohammad MursaleenView Answer on Stackoverflow
Solution 7 - Phpahmet alp balkanView Answer on Stackoverflow
Solution 8 - PhpRounin - Standing with UkraineView Answer on Stackoverflow
Solution 9 - PhpupfulView Answer on Stackoverflow
Solution 10 - PhpPhilippView Answer on Stackoverflow
Solution 11 - PhpLewis DonovanView Answer on Stackoverflow
Solution 12 - PhpMatthew AndersonView Answer on Stackoverflow
Solution 13 - PhpRameez RamiView Answer on Stackoverflow
Solution 14 - PhpParsaView Answer on Stackoverflow
Solution 15 - Phpuser11995521View Answer on Stackoverflow
Solution 16 - PhpAhad AliView Answer on Stackoverflow
Solution 17 - PhpSergey OnishchenkoView Answer on Stackoverflow
Solution 18 - Phph0mayunView Answer on Stackoverflow
Solution 19 - PhpGreco JonathanView Answer on Stackoverflow
Solution 20 - PhpTinh DangView Answer on Stackoverflow
Solution 21 - PhpJackView Answer on Stackoverflow
Solution 22 - Phpmaxpower9000View Answer on Stackoverflow
Solution 23 - PhpmiladView Answer on Stackoverflow
Solution 24 - PhpRobert JohnstoneView Answer on Stackoverflow
Solution 25 - Phpkalicki2kView Answer on Stackoverflow
Solution 26 - Phpuser10012View Answer on Stackoverflow
Solution 27 - Phpאיש נחמדView Answer on Stackoverflow
Solution 28 - PhpNVRMView Answer on Stackoverflow
Solution 29 - PhpbiziclopView Answer on Stackoverflow
Solution 30 - PhpGONZOView Answer on Stackoverflow
Solution 31 - Phpuser4395445View Answer on Stackoverflow
Solution 32 - Phpuser11487450View Answer on Stackoverflow