Kir*_*met 355 php error-handling json jsonresult json-deserialization
我需要一种非常非常快速的检查字符串是否为JSON的方法.我觉得这不是最好的方法:
function isJson($string) {
return ((is_string($string) &&
(is_object(json_decode($string)) ||
is_array(json_decode($string))))) ? true : false;
}
Run Code Online (Sandbox Code Playgroud)
任何表演爱好者都想改进这种方法吗?
Hen*_*sel 542
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
Run Code Online (Sandbox Code Playgroud)
Mad*_*ota 147
回答问题
该函数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
}
Run Code Online (Sandbox Code Playgroud)
请注意,json_last_errorPHP> = 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;
}
Run Code Online (Sandbox Code Playgroud)
使用有效的JSON INPUT进行测试
$json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
$output = json_validate($json);
print_r($output);
Run Code Online (Sandbox Code Playgroud)
有效输出
Array
(
[0] => stdClass Object
(
[user_id] => 13
[username] => stack
)
[1] => stdClass Object
(
[user_id] => 14
[username] => over
)
)
Run Code Online (Sandbox Code Playgroud)
使用无效的JSON进行测试
$json = '{background-color:yellow;color:#000;padding:10px;width:650px;}';
$output = json_validate($json);
print_r($output);
Run Code Online (Sandbox Code Playgroud)
无效的输出
Syntax error, malformed JSON.
Run Code Online (Sandbox Code Playgroud)
额外注意事项(PHP> = 5.2 && PHP <5.3.0)
由于json_last_errorPHP 5.2不支持,您可以检查编码或解码是否返回布尔值FALSE.这是一个例子
// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
// JSON is invalid
}
Run Code Online (Sandbox Code Playgroud)
希望这是有帮助的.快乐的编码!
小智 75
你真正需要做的就是......
if (is_object(json_decode($MyJSONArray)))
{
... do something ...
}
Run Code Online (Sandbox Code Playgroud)
此请求甚至不需要单独的功能.只需在json_decode周围包装is_object并继续.似乎这个解决方案让人们对此过于考虑.
mar*_*rio 70
使用json_decode"探测"它实际上可能不是最快的方式.如果它是一个深度嵌套的结构,那么实例化大量的数组对象只是扔掉它们是浪费内存和时间.
因此,使用preg_match和RFC4627正则表达式可能更快,以确保有效性:
// in JS:
var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
text.replace(/"(\\.|[^"\\])*"/g, '')));
Run Code Online (Sandbox Code Playgroud)
在PHP中也一样:
return !preg_match('/[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]/',
preg_replace('/"(\\.|[^"\\\\])*"/', '', $json_string));
Run Code Online (Sandbox Code Playgroud)
然而,这里没有足够的性能爱好者来打扰基准测试.
Cyr*_*ril 37
如果您的字符串表示json数组或对象,则返回true:
function isJson($str) {
$json = json_decode($str);
return $json && $str != $json;
}
Run Code Online (Sandbox Code Playgroud)
它拒绝只包含数字,字符串或布尔值的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)
Run Code Online (Sandbox Code Playgroud)
这是我能想到的最短路.
Moh*_*een 20
我使用的最简单,最快捷的方法是遵循;
$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
Run Code Online (Sandbox Code Playgroud)
这是因为如果输入的字符串不是json或无效的json ,则 json_decode()返回NULL.
如果必须在多个位置验证JSON,则始终可以使用以下功能.
function is_valid_json( $raw_json ){
return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}
Run Code Online (Sandbox Code Playgroud)
在上面的函数中,如果它是有效的JSON,你将得到回报.
Ahm*_*gle 17
function is_json($str){
return json_decode($str) != null;
}
Run Code Online (Sandbox Code Playgroud)
检测到无效编码时,http://tr.php.net/manual/en/function.json-decode.php返回值为null.
Rou*_*ica 14
昨天在我的工作中遇到类似的事情后,我发现了这个问题。最后,我的解决方案是上述一些方法的混合:
function is_JSON($string) {
return (is_null(json_decode($string))) ? FALSE : TRUE;
}
Run Code Online (Sandbox Code Playgroud)
upf*_*ful 11
您必须验证输入以确保您传递的字符串不为空,实际上是一个字符串.空字符串无效JSON.
function is_json($string) {
return !empty($string) && is_string($string) && is_array(json_decode($string, true)) && json_last_error() == 0;
}
Run Code Online (Sandbox Code Playgroud)
我认为在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;
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*son 10
将 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);
}
}
Run Code Online (Sandbox Code Playgroud)
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 |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
Run Code Online (Sandbox Code Playgroud)
结论:检查 json 是否有效的最快方法是返回json_decode($json, true) !== null).
简单的方法是检查json结果..
$result = @json_decode($json,true);
if (is_array($result)) {
echo 'JSON is valid';
}else{
echo 'JSON is not valid';
}
Run Code Online (Sandbox Code Playgroud)
这样做:
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";
}
Run Code Online (Sandbox Code Playgroud)
虽然仍在开发中的 PHP 8.3 将配备新的内存高效json_validate()功能,但由于令人惊叹的Symfony Polyfill组件,您可以将其与旧版 PHP 版本(7.1 及更高版本)一起使用。
只需将以下包添加到您的项目中:
composer require symfony/polyfill-php83
Run Code Online (Sandbox Code Playgroud)
并在您的应用程序中使用它:
if (json_validate($data)) {
// do sometihng
}
Run Code Online (Sandbox Code Playgroud)
通过这种方法,您可以在旧应用程序中使用新的 PHP 功能,并在将来迁移到 PHP 8.3,而无需更改任何代码,因为您的代码将自动使用可用的内置函数。
小智 6
/**
* 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;
}
Run Code Online (Sandbox Code Playgroud)
小智 6
//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;
}
Run Code Online (Sandbox Code Playgroud)
json_validate()函数的 RFC已实现,并将成为 PHP 8.3 的一部分
这种方法将是实现问题所要求的最快、最有效的方法。
早些时候我只是检查一个空值,实际上这是错误的.
$data = "ahad";
$r_data = json_decode($data);
if($r_data){//json_decode will return null, which is the behavior we expect
//success
}
Run Code Online (Sandbox Code Playgroud)
上面的代码可以很好地处理字符串.但是,只要我提供号码,它就会崩溃.例如.
$data = "1213145";
$r_data = json_decode($data);
if($r_data){//json_decode will return 1213145, which is the behavior we don't expect
//success
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我所做的非常简单.
$data = "ahad";
$r_data = json_decode($data);
if(($r_data != $data) && $r_data)
print "Json success";
else
print "Json error";
Run Code Online (Sandbox Code Playgroud)
我们需要检查传递的字符串是否不是数字,因为在这种情况下 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;
}
Run Code Online (Sandbox Code Playgroud)
最快的方法是“可能解码”可能的 JSON 字符串
如果你想解码复杂的对象或更大的数组,这是迄今为止最快的方法!
如果您的 json 字符串包含短值(如标量或只有 1-2 个属性的对象),那么此 SO 问题中的所有解决方案都具有类似的性能。
这是我使用一些虚拟和真实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
Run Code Online (Sandbox Code Playgroud)
最后一行是这个答案的代码,这是“也许解码”的方法。
这是性能比较脚本,您可以在那里看到我用于比较的测试数据:https : //gist.github.com/stracker-phil/6a80e6faedea8dab090b4bf6668ee461
在尝试解码 JSON 字符串之前,我们首先执行一些类型检查和字符串比较。这为我们提供了最佳性能,因为 json_decode() 可能很慢。
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
Run Code Online (Sandbox Code Playgroud)
此函数使用相同的逻辑,但返回解码后的 JSON 对象或原始值。
我在递归解码复杂对象的解析器中使用此函数。某些属性可能已被较早的迭代解码。该函数识别出这一点,并且不会再次尝试对该值进行双重解码。
/**
* Returns true, when the given parameter is a valid JSON string.
*/
function is_json( $value ) {
// A non-string value can never be a JSON string.
if ( ! is_string( $value ) ) { return false; }
// Numeric strings are always valid JSON.
if ( is_numeric( $value ) ) { return true; }
// 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; }
// Note the last param (1), this limits the depth to the first level.
$json_data = json_decode( $value, null, 1 );
// When json_decode fails, it returns NULL.
if ( is_null( $json_data ) ) { return false; }
return true;
}
Run Code Online (Sandbox Code Playgroud)
注意:在此 SO 问题中将非字符串传递给任何其他解决方案时,您将获得显着降低的性能+ 错误的返回值(甚至致命错误)。此代码是防弹且高性能的。
| 归档时间: |
|
| 查看次数: |
312073 次 |
| 最近记录: |