在PHP中检查字符串是否为JSON的最快方法?

我需要一个非常非常快的方法来检查字符串是否为JSON。我觉得这不是最好的方式:

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

有没有表演爱好者想改进这种方法?

505830 次浏览
function isJson($string) {
json_decode($string);
return json_last_error() === JSON_ERROR_NONE;
}
function is_json($str){
return json_decode($str) != null;
}

当检测到非法编码时,http://tr.php.net/manual/en/function.json-decode.php返回值为空。

使用json_decode来“探测”它实际上可能不是最快的方法。如果它是一个嵌套很深的结构,那么实例化大量数组对象来丢弃它们是浪费内存和时间。

因此,使用preg_matchRFC4627 regex来同时使用确保有效性可能会更快:

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

在PHP中也一样:

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

不过,我不是一个性能爱好者,不会在这里费心进行基准测试。

你真正需要做的就是…

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

这个请求甚至不需要一个单独的函数。只需将is_object包装在json_decode周围,然后继续。似乎这个解决方案让人们花了太多心思。

我不知道我的解决方案的性能或优雅性,但这就是我正在使用的:

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

因为我所有的JSON编码字符串都以{”开头,所以用RegEx进行测试就足够了。我对RegEx一点也不流利,所以可能有更好的方法来做到这一点。还有:(大小写敏感)可能更快。

我只是想贡献我的价值。

附:刚刚将RegEx字符串更新为/^[\[\{]\"/,也可以找到JSON数组字符串。所以它现在在字符串的开头寻找["或{"。

问题的答案

函数json_last_error返回JSON编码和解码过程中发生的最后一个错误。因此,检查有效JSON的最快方法是

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

注意json_last_error仅在PHP >= 5.3.0中支持。

完整的程序来检查准确的错误

在开发期间了解准确的错误总是好的。下面是基于PHP文档检查确切错误的完整程序。

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

使用有效的JSON INPUT进行测试

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

有效的输出

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


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

使用无效JSON进行测试

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

无效的输出

Syntax error, malformed JSON.

额外注意(PHP >= 5.2 &&PHP & lt;5.3.0)

由于PHP 5.2中不支持json_last_error,因此可以检查编码或解码是否返回布尔值FALSE。这里有一个例子

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

您必须验证您的输入,以确保您传递的字符串不是空的,实际上是一个字符串。空字符串不是有效的JSON。

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

我认为在PHP中,更重要的是确定JSON对象是否甚至是数据,因为要使用数据,您将需要调用json_encode()json_decode()。我建议拒绝空JSON对象,这样就不必在空数据上运行编码和解码。

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

另一种简单的方法

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

之前我只是检查一个空值,这实际上是错误的。

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

上面的代码可以很好地处理字符串。然而,只要我提供号码,它就中断了。为例。

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


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

要修复它,我所做的很简单。

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


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

我使用的最简单和最快的方法是跟随;

$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

这是因为如果输入的字符串不是json或无效的json, json_decode ()将返回NULL。


验证JSON的简单函数

如果您必须在多个地方验证JSON,您总是可以使用下面的函数。

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

在上面的函数中,如果它是一个有效的JSON,则返回true。

为PHP 5.2兼容性新创建的函数,如果你需要成功解码的数据:

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

用法:

$json_or_not = ...;


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


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

一些测试:

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)

这个答案上扩展如何:

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

我们需要检查传递的string是否不是数字,因为在这种情况下json_decode不会引发错误。

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


return $result;
}

简单的方法是检查json结果..

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

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

如果字符串表示Json数组或对象,则返回真正的:

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

它拒绝只包含数字、字符串或布尔值的json字符串,尽管这些字符串在技术上是有效的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)

这是我能想到的最短的方法了。

对亨里克的回答做一个简单的修改,以触及最需要的可能性。

(包括“{}和[]”)

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;


}

最快的方法是“也许解码"可能的JSON字符串

这真的是最快的方法吗?

如果你想解码复杂的对象或更大的数组,这是最快的解决方案! 除了速度快,这是唯一的解决方案,可以可靠地处理任何类型的输入值-其他函数抛出错误或在某些情况下返回不正确的结果

如果你的JSON字符串包含较短的值(例如,字符串,数字或只有1-2个属性的对象),那么这个SO问题中的所有解决方案都是相似的性能

这里有一个快速的概览和比较-您可以在链接的要点中找到测试用例。最后一列使用了这个答案的代码:

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

请注意,最快的解决方案会产生最不正确的结果。从所有其他解决方案中,“可能解码”;方法不仅是最快的,而且是唯一能得到正确结果的解决方法。

下面是完整的性能比较脚本,在那里你可以看到我用于比较的测试数据:https://gist.github.com/stracker-phil/6a80e6faedea8dab090b4bf6668ee461


“也许解码”;逻辑/代码

在尝试解码JSON字符串之前,我们首先执行一些类型检查和字符串比较。这为我们提供了最佳性能,因为json_decode()可能很慢。

/**
* 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 true; }


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

额外:使用此逻辑安全地对JSON进行双重解码

此函数使用相同的逻辑,但要么是返回解码后的JSON对象,要么是原始值. c。

我在递归解码复杂对象的解析器中使用了这个函数。一些属性可能已经被早期的迭代解码了。该函数识别此值,并且不再尝试再次对值进行双解码。

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

注意:当将non-string传递给这个SO问题中的任何其他解决方案时,你将得到性能急剧下降 +错误的返回值(甚至是致命错误)。此代码是防弹和高性能的。

我试过其中的一些方法,但没有一种对我有效。我尝试了这么简单的事情:

$isJson = json_decode($myJSON);


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

我认为这是一个很好的解决方案,因为JSON解码没有第二个参数给出一个对象。

编辑:如果知道输入内容,就可以根据需要调整代码。在我的情况下,我知道我有一个Json以“{”开始,所以我不需要检查它是否是一个数组。

应该是这样的:

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

这样就可以了:

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

如其他答案所示,json_last_error()返回来自上一次json_decode()的任何错误。然而,在一些边缘用例中,仅使用这个功能还不够全面。例如,如果你json_decode()一个整数(例如:123),或者一个没有空格或其他字符的数字字符串(例如:"123"), json_last_error()函数将不会捕获错误。

为了解决这个问题,我增加了一个额外的步骤,以确保json_decode()的结果是一个对象或数组。如果不是,则返回false

要查看具体操作,请查看以下两个示例:

嗨,这是我的库中的一个小片段,在第一个条件下,我只是检查数据是否为json,然后返回它,如果正确解码,请注意substr的使用性能(我还没有看到任何json文件不以{或[开始

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

我的另一个建议:)

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

下面是我创建的一个简单的性能函数(在使用json_decode对更大的字符串使用之前,使用基本的字符串验证):

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

使用PHPBench和下面的类,得到了以下结果:

<?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 |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+


结论:检查json是否有效的最快方法是返回json_decode($json, true) !== null)

昨天,我在工作中遇到了类似的问题,我发现了这个问题。我的解决方案是以上几种方法的混合:

function is_JSON($string) {


return is_null(json_decode($string));
}
//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;
}

这就是我的建议

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);
}
$r = (array)json_decode($arr);
if(!is_array($r) || count($r) < 1) return false;

如果本地文件stations.json无效、缺失或超过一个月,请采取措施。

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
}
function isJson($string) {
$obj = json_decode($string);
return json_last_error() === JSON_ERROR_NONE && gettype($obj ) == "object";
}

这是有效的,对于数字不返回true

新的更新

如果JSON很长并且你不需要使用$obj,上面的解决方案就没有很好的性能

如果你只是想检查一下,最好使用下面的函数

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

更新:json_validate()将在PHP 8.3中上线

仅供参考:

我正在研究一个RFC,在php中添加一个新函数,它能够验证—只验证json字符串,而不生成对象/数组。

为什么是只验证的函数?因为json_decode()在解析json-string时创建了一个数组/对象,这会影响正在使用的内存量;这意味着在验证json字符串时可以达到最大内存限制。

为了给你一个概念,检查这个代码_vs_json_decode performance_test_json_validate () ():

在这个测试中,我们可以看到新函数json_validate ()使用了0 MB来验证json字符串,而json_decode ()需要109 MB来做这件事(因为它在解析时创建了一个内存数组/对象)。

这是目前正在进行的工作,但我发布这篇文章是因为我对你对它的看法很感兴趣(我的意思是,从技术角度来看,不是你认为值得拥有它)。

Github: https://github.com/php/php-src/pull/9399

RFC(工作进行中):https://wiki.php.net/rfc/json_validate

期待您的意见/支持。

提前谢谢你。

我知道这个问题很老了,但我想通知大家,json_validate ()函数的RFC已经实现,并将成为php 8.3的一部分

这种方法将是实现问题要求的最快和更有效的方法。

github -实现代码

rfc - of json_validate()