我需要一种非常快的方法来检查一个字符串是否是JSON格式。我觉得下面的方法不是最好的:
function isJson($string) {
return ((is_string($string) &&
(is_object(json_decode($string)) ||
is_array(json_decode($string))))) ? true : false;
}
有没有性能爱好者想要改进这个方法?
我需要一种非常快的方法来检查一个字符串是否是JSON格式。我觉得下面的方法不是最好的:
function isJson($string) {
return ((is_string($string) &&
(is_object(json_decode($string)) ||
is_array(json_decode($string))))) ? true : false;
}
有没有性能爱好者想要改进这个方法?
function isJson($string) {
json_decode($string);
return json_last_error() === JSON_ERROR_NONE;
}
{
、[
或任何其他文字的第一个符号,可以在预计许多传入字符串为非 JSON 时大大提高速度。 - Oleg V. Volkov6.5 = true, '300' = true, 9 = true
等等。因此,这可能是一个有效的JSON值,但如果您只想检查具有{}
或[]
的有效JSON字符串,则该函数可能不会按照您的预期行事。 - BadHorsiejson_decode
函数存在许多 bug,这些 bug 会以奇怪的方式解析无效的 JSON。isJson('0123')
应该返回 false
,因为 0123
不是 JSON,然而 isJson('123')
应该返回 true
,因为 123
是 JSON。似乎有些人不知道 JSON 允许值不仅仅是对象或数组。有效的 JSON 值可以是对象、数组、数字、字符串、布尔值和 null
。 - zzzzBov问题的答案
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输入进行测试
$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);
Invalid OUTPUT
Syntax error, malformed JSON.
对于 (PHP >= 5.2 && PHP < 5.3.0) 版本的额外说明
由于在 PHP 5.2 中不支持 json_last_error
,你可以检查编码或解码是否返回布尔值 FALSE
。以下是一个示例。
// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
// JSON is invalid
}
((strlen($json) === 5) && ($json !== 'false'))
以避免这种情况。 - MrMeseesjson_last_error
返回 JSON_ERROR_NONE
。 - Andrea你真正需要做的只是这个...
if (is_object(json_decode($MyJSONArray)))
{
... do something ...
}
甚至不需要单独的函数,只需将is_object包装在json_decode周围即可。看起来这个解决方案让人们想得太多了。
is_object
之前使用is_array
,否则对于编码为JSON的简单数组,is_object
将返回false。所以在这种情况下@ggutenberg是正确的。向json_decode
传递true参数会强制返回一个对象作为数组。理论上,您可以始终将解码强制为数组,并仅检查is_array
,这应该可以正常工作。 - userabuserjson_encode($array)
,然后执行json_decode($str)
,我将收到对象,而不是数组。 json_decode($str, true)
强制转换为数组。为什么在您的代码中使用复杂的字符串?
检查 is_array(json_decode($str, true))
,稍后当您阅读它时,您将了解解码必须只是一个数组。更难猜测 is_object(json_decode($MyJSONArray))
“哦,这里我正在检查解码是否为数组?” - Roman M. Kossjson_decode
返回一个数组来省去检查对象和数组的步骤,但是如果你没有做到这一点,并且你开始只有一个简单的数组,当你使用 json_decode
时,你将会得到一个数组而不是一个对象。如果您要始终在传递一个简单的数组时强制使用对象进行编码,则必须使用 JSON_FORCE_OBJECT
。 - userabuserjson_decode
进行“探测”可能不是最快的方法。如果它是一个深层嵌套的结构,则实例化许多对象和数组只是为了将它们丢弃,这是浪费内存和时间的。因此,使用 preg_match
和 RFC4627 正则表达式 也可以 确保有效性,从而更快地完成任务。 // 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));
我不够热衷于性能,不会在这里打扰进行基准测试。
json_decode
总是比PCRE正则表达式更快。 (虽然它没有经过很好的优化,没有找到综合测试,并且在Perl中可能会有不同的行为..) - mario如果你的字符串表示一个JSON数组或对象,这将返回true:
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)
这是我能想到的最简洁的方式。
isJson('hello')
评估为 true,这不是有效的 json。这里故意选择了松散比较。对于空数组/对象情况,我没有快速解决方案,除了一个丑陋的 return $json == '[]' || ...
。 - Cyriljson_decode
之前短路函数的其他检查。因为“hello”字符串触发了JSON错误,所以函数的输出是NULL
,因此额外的!is_null
检查足以使用您的测试数据产生正确的结果:return $json !== false && !is_null($json) && $str != $json;
- j13k最快的方法是“可能解码”可能的JSON字符串。
如果你想解码复杂对象或更大的数组,这是最快的解决方案!除了速度快外,这也是唯一可以可靠地处理任何类型输入值的解决方案 - 其他函数在某些情况下会抛出错误或返回不正确的结果。
如果你的JSON字符串包含短值(比如字符串、数字或只有1-2个属性的对象),那么所有在该 SO 问题中提供的解决方案都会有类似的性能。
以下是一个快速概述和比较 - 你可以在链接的 gist 中找到测试用例。最后一列使用了本答案中提供的代码:
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
请注意,最快的解决方案会产生最不准确的结果。在所有其他解决方案中,“maybe decode”方法不仅是最快的,而且还是唯一能产生正确结果的解决方案。
这是完整的性能比较脚本,您可以在其中看到我用于比较的测试数据: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对象,要么返回原始值。
我在一个解析器中使用此函数,该解析器递归解码复杂对象。一些属性可能已经被早期迭代解码了。该函数识别到这一点后不会再尝试对该值进行双重解码。
/**
* 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;
}
注意:在此SO问题的任何其他解决方案中传递非字符串时,您将获得极大降级的性能+错误返回值(甚至致命错误)。此代码经过强化并具有高性能。
json_decode
更短,但需要PHP初始化一个内部JSON解析器实例,这相当复杂且比8个简单的if
慢得多。 - Philipp我使用的最简单、最快的方法如下:
$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,可以使用以下函数。
function is_valid_json( $raw_json ){
return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}
在上述函数中,如果它是有效的JSON,则会返回true。
json_decode('null') == NULL
并且 null
是一个有效的 JSON 值。 - zzzzBovPHP 8.3
原生 PHP 函数
json_validate(string $json, int $depth = 512, int $flags = 0): bool
https://wiki.php.net/rfc/json_validate
PHP < 8.3
您必须验证输入以确保传递的字符串不为空,并且实际上是一个字符串。空字符串不是有效的 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;
}
'0'
不是有效的JSON...我为什么要小心?@Kzqai - upfulif(is_string($string) && is_array(json_decode($string, true)) && (json_last_error() == JSON_ERROR_NONE)){ // json is valid }else{ // not valid }
- Harsh Pateltrue
、false
和null
的值也是如此。而且,您永远不应该在常量的位置使用固定值。 - undefinedfunction is_json($str){
return json_decode($str) != null;
}
http://tr.php.net/manual/zh/function.json-decode.php在检测到无效编码时返回Null。
json_decode($str)!=null;
,否则函数应该被命名为is_not_json
。 - Yoshiis_json('false')
е’Ңis_json('[]')
е°Ҷиҝ”еӣһfalse
пјҢеӣ дёәзұ»еһӢжңӘз»ҸжЈҖжҹҘгҖӮжҲ‘и®ӨдёәиҝҷдёӘж–№жі•еә”иҜҘиҝ”еӣһ$str === null || json_decode($str) !== null
гҖӮ - Antoine Pinsard在昨天的工作中,我发现了一个类似的问题,并在阅读上述方法后,最终采用了一种混合方案。
function is_JSON($string) {
return (is_null(json_decode($string))) ? FALSE : TRUE;
}
if (is_null($string)) return TRUE;
。 - Rouninreturn is_null(json_decode($string));
。 - hanshenrik$string
返回true
...因此:return !is_null(json_decode($string));
- berendreturn (is_null(json_decode($string))) ? FALSE : TRUE;
。后来,我把它改成了:return is_null(json_decode($string));
。我不知道当时在想什么。现在我已经改回去了。再次感谢。 - Rounin
json_decode
,并检查其输入和返回值。 - user166390