在PHP中检查字符串是否为JSON的最快方法?
我需要一种非常非常快速的方法来检查字符串是否为JSON。我觉得这不是最好的方式:在PHP中检查字符串是否为JSON的最快方法?,php,json,error-handling,json-deserialization,jsonresult,Php,Json,Error Handling,Json Deserialization,Jsonresult,我需要一种非常非常快速的方法来检查字符串是否为JSON。我觉得这不是最好的方式: function isJson($string) { return ((is_string($string) && (is_object(json_decode($string)) || is_array(json_decode($string))))) ? true : false; } 有没有性能爱好者想要改进这种方法 function
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;
}
当检测到无效编码时,返回值为null。使用“探测”实际上可能不是最快的方法。如果它是一个深度嵌套的结构,那么实例化大量数组对象以将其丢弃就是浪费内存和时间
因此,它可能会更快地使用,正则表达式也可以确保有效性:
在PHP中也是如此:
return !preg_match('/[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]/',
preg_replace('/"(\\.|[^"\\\\])*"/', '', $json_string));
然而,对于性能狂热者来说,这里没有足够的基准测试 你真正需要做的就是
if(是_对象(json_decode($MyJSONArray)))
{
…做点什么。。。
}
此请求甚至不需要单独的函数。只需将is_对象围绕json_解码并继续。似乎这个解决方案让人们想得太多了。我不知道我的解决方案的性能或优雅程度,但我使用的是:
if (preg_match('/^[\[\{]\"/', $string)) {
$aJson = json_decode($string, true);
if (!is_null($aJson)) {
... do stuff here ...
}
}
因为我所有的JSON编码字符串都以{“开头,所以用正则表达式测试就足够了。我对正则表达式一点也不流利,所以可能有更好的方法来做到这一点。另外:可能更快
我只是想放弃我的一便士
另外,刚刚将正则表达式字符串更新为/^[\[\{]\“/
,以同时查找JSON数组字符串。因此,它现在在字符串的开头查找[”或{”
问题的答案
function custom_json_decode(&$contents=NULL, $normalize_contents=true, $force_array=true){
//---------------decode contents---------------------
$decoded_contents=NULL;
if(is_string($contents)){
$decoded_contents=json_decode($contents,$force_array);
}
//---------------normalize contents---------------------
if($normalize_contents===true){
if(is_string($decoded_contents)){
if($decoded_contents==='NULL'||$decoded_contents==='null'){
$contents=NULL;
}
elseif($decoded_contents==='FALSE'||$decoded_contents==='false'){
$contents=false;
}
}
elseif(!is_null($decoded_contents)){
$contents=$decoded_contents;
}
}
else{
//---------------validation contents---------------------
$contents=$decoded_contents;
}
return $contents;
}
函数
json\u last\u 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\u last\u 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进行测试
无效输出
额外注意(PHP>=5.2和&PHP<5.3.0)
由于PHP 5.2不支持json\u last\u 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,则返回NULL
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)
验证JSON的简单函数 如果必须在多个位置验证JSON,则始终可以使用以下函数
function is_valid_json( $raw_json ){
return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}
在上述函数中,如果它是有效的JSON,则返回true。自定义函数
function is_json($string) {
return !empty($string) && is_string($string) && is_array(json_decode($string, true)) && json_last_error() == 0;
}
function custom_json_decode(&$contents=NULL, $normalize_contents=true, $force_array=true){
//---------------decode contents---------------------
$decoded_contents=NULL;
if(is_string($contents)){
$decoded_contents=json_decode($contents,$force_array);
}
//---------------normalize contents---------------------
if($normalize_contents===true){
if(is_string($decoded_contents)){
if($decoded_contents==='NULL'||$decoded_contents==='null'){
$contents=NULL;
}
elseif($decoded_contents==='FALSE'||$decoded_contents==='false'){
$contents=false;
}
}
elseif(!is_null($decoded_contents)){
$contents=$decoded_contents;
}
}
else{
//---------------validation contents---------------------
$contents=$decoded_contents;
}
return $contents;
}
案例
$none_json_str='hello';
//------------decoding a none json str---------------
$contents=custom_json_decode($none_json_str); // returns 'hello'
//------------checking a none json str---------------
custom_json_decode($none_json_str,false);
$valid_json=false;
if(!is_null($none_json_str)){
$valid_json=true;
}
资源
$none_json_str='hello';
//------------decoding a none json str---------------
$contents=custom_json_decode($none_json_str); // returns 'hello'
//------------checking a none json str---------------
custom_json_decode($none_json_str,false);
$valid_json=false;
if(!is_null($none_json_str)){
$valid_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);
?>
我们需要检查传递的字符串是否不是数字,因为在这种情况下,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';
}
在:
如果字符串表示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)
这是我能想到的最短的方法。对henrik的答案进行简单修改,以触及最需要的可能性 (包括“{}和[]”) 最快的方法是“可能解码”可能的JSON字符串 这真的是最快的方法吗? 如果您想解码复杂对象或更大的数组,这是迄今为止最快的方法 如果您的json字符串包含短值(如标量或只有1-2个属性的对象),那么此问题中的所有解决方案都具有类似的性能 下面是我与一些虚拟和真实的实时JSON值进行的性能比较:
PHP version: 7.4.12
1 | Duration: 1.5828 sec | 60,000 calls | json_last_error() == JSON_ERROR_NONE
2 | Duration: 1.5202 sec | 60,000 calls | is_object( json_decode() )
3 | Duration: 1.5400 sec | 60,000 calls | json_decode() && $res != $string
4 | Duration: 1.3536 sec | 60,000 calls | preg_match()
5 | Duration: 0.2261 sec | 60,000 calls | "maybe decode" approach
最后一行是这个答案中的代码,这是“可能解码”方法。
这是性能比较脚本,您可以看到我用于比较的测试数据:
“可能解码”逻辑/代码 在尝试解码JSON字符串之前,我们首先执行一些类型检查和字符串比较。这为我们提供了最佳性能,因为JSON_decode()可能会很慢
/**
*当给定参数是有效的JSON字符串时,返回true。
*/
函数为_json($value){
//非字符串值永远不能是JSON字符串。
如果(!is_string($value)){return false;}
//数字字符串始终是有效的JSON。
如果(是数值($value)){return true;}
//任何非数字JSON字符串必须超过2个字符。
if(strlen($value)<2){返回false;}
//“null”是有效的JSON字符串。
如果('null'=$value){return true;}
//“true”和“false”是有效的JSON字符串。
如果('true'=$value){retu
/**
* 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;
}
function isJson($str) {
$json = json_decode($str);
return $json && $str != $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;
}
PHP version: 7.4.12
1 | Duration: 1.5828 sec | 60,000 calls | json_last_error() == JSON_ERROR_NONE
2 | Duration: 1.5202 sec | 60,000 calls | is_object( json_decode() )
3 | Duration: 1.5400 sec | 60,000 calls | json_decode() && $res != $string
4 | Duration: 1.3536 sec | 60,000 calls | preg_match()
5 | Duration: 0.2261 sec | 60,000 calls | "maybe decode" approach
$isJson = json_decode($myJSON);
if ($isJson instanceof \stdClass || is_array($isJson)) {
echo("it's JSON confirmed");
} else {
echo("nope");
}
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;
}
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);
}
}
$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
}
}
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 |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
function is_JSON($string) {
return (is_null(json_decode($string))) ? FALSE : TRUE;
}
//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;
}
$r = (array)json_decode($arr);
if(!is_array($r) || count($r) < 1) return false;
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
}