我需要一个非常非常快的方法来检查字符串是否为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;
}
有没有表演爱好者想改进这种方法?
当前回答
$r = (array)json_decode($arr);
if(!is_array($r) || count($r) < 1) return false;
其他回答
之前我只是检查一个空值,这实际上是错误的。
$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";
在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;
}
另一种简单的方法
function is_json($str)
{
return is_array(json_decode($str,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);
?>
使用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)。