我需要一种非常非常快速的方法来检查字符串是否为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;
}
是否有任何性能发烧友想改进此方法?
Answers:
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
{
,则检查string的第一个字符是否为,[
或其他任何文字的第一个符号都可以极大地加快此速度。
6.5 = true, '300' = true, 9 = true
因此,这可能是有效的JSON值,但是如果您只想使用{}
或来检查有效的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 <5.3.0)的附加说明
由于json_last_error
PHP 5.2不支持,因此您可以检查编码或解码是否返回boolean FALSE
。这是一个例子
// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
// JSON is invalid
}
希望这会有所帮助。编码愉快!
((strlen($json) === 5) && ($json !== 'false'))
还应该进行检查以避免出现这种情况?
json_last_error
返回JSON_ERROR_NONE
。
您真正需要做的就是...
if (is_object(json_decode($MyJSONArray)))
{
... do something ...
}
该请求甚至不需要单独的功能。只需在json_decode周围包裹is_object并继续。似乎这种解决方案使人们投入了太多的思考。
is_array
除了需要使用之外is_object
,否则is_object
对于编码为JSON的简单数组,将返回false。因此,@ ggutenberg在这种情况下是正确的。传递true参数以json_decode
强制将对象作为数组返回。从理论上讲,您可以始终将解码强制为数组,然后只需检查即可is_array
。
json_encode($array)
使用简单的PHP数组,那么json_decode($str)
我将接收对象,但不接收数组。json_decode($str, true)
强制转换为数组。为什么在代码中使用复杂的字符串?检查一下,is_array(json_decode($str, true))
稍后阅读时,您将了解已解码必须仅是一个数组。很难猜测is_object(json_decode($MyJSONArray))
“哦,在这里我要检查解码的是数组还是不是数组?”
json_decode
返回一个数组以保存对对象和数组的检查,但是如果不这样做json_decode
又该怎么办首先是一个简单的数组,您将收到一个解码返回的数组,而不是对象。JSON_FORCE_OBJECT
如果要始终在传递简单数组的编码IF上强制对象,则必须使用。
This request does not require a separate function even
。严格来说,没有解决方案需要单独的功能。函数的重点不是使多行代码看起来像一行代码。该功能的要点是在您的应用程序中的所有地方都使JSON检查过程成为标准,以便不同的程序员(或者随着时间的推移同一个程序员)在程序流程的不同阶段不使用不同的检查过程。
使用json_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中的表现可能有所不同。)
\r
\n
\t
这很有意义,所以PHP不会对它们进行插值,而是让PCRE解释它们(仅/x
模式需要)。其他事件并不严格需要它。但在所有字符串PHP上下文中仍然存在“反斜杠本身”。因此,可以认为它更精确。
如果您的字符串表示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)
这是我想出的最短方法。
var_dump(isJson('[]')); // bool(false)
。根据有关布尔值的文档,这是因为PHP将零元素的数组评估为false。这是对返回声明进行调整的一个小修改;它对处理这种情况的解码输出执行相同的比较:return $json !== false && $str != $json;
isJson('hello')
为true,这不是有效的json。在这里故意选择松散比较。我没有针对空数组/对象情况的快速解决方案,除了一个丑陋的问题return $json == '[]' || ...
我使用的最简单,最快的方法是:
$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值。
JSON.parse('null')
在您的开发控制台中尝试。
function is_json($str){
return json_decode($str) != null;
}
如果检测到无效编码,则http://tr.php.net/manual/zh-CN/function.json-decode.php返回值为null。
json_decode($str)!=null;
否则应调用函数is_not_json
。
json_decode('null')
根据规范为有效JSON,应返回的值null
。
is_json('false')
并is_json('[]')
会false
在未检查类型的情况下返回。我认为这种方法应该返回$str === null || json_decode($str) !== null
。
您必须验证输入内容,以确保传递的字符串不为空,并且实际上是字符串。空字符串不是有效的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
这样做:
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
。
要查看实际效果,请查看以下两个示例:
"hello"
是有效的JSON,它不是对象,也不是数组,json_last_error()
就足够了
简单的方法是检查json结果。
$result = @json_decode($json,true);
if (is_array($result)) {
echo 'JSON is valid';
}else{
echo 'JSON is not valid';
}
/**
* 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;
}
之前我只是检查一个空值,实际上这是错误的。
$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";
另一种简单的方法
function is_json($str)
{
return is_array(json_decode($str,true));
}
json_decode($str,true)
使它可以将对象转换为数组,因此它将通过is_array检查。您可以对字符串,整数等进行更正。
我已经尝试了其中一些解决方案,但没有任何工作对我有用。我尝试这个简单的事情:
$isJson = json_decode($myJSON);
if ($isJson instanceof \stdClass || is_array($isJson)) {
echo("it's JSON confirmed");
} else {
echo("nope");
}
我认为这是一个很好的解决方案,因为不带第二个参数的JSON解码给出了一个对象。
编辑:如果您知道输入的内容,则可以根据需要调整此代码。就我而言,我知道我有一个以“ {”开头的Json,所以我不需要检查它是否为数组。
将PHPBench与以下类一起使用,可获得以下结果:
<?php
declare(strict_types=1);
/**
* Benchmark doctrine persistent collection count method vs sizeof toArray
* Revs is the number of times you want the benchmark to run
* @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是否有效的最快方法是return json_decode($json, true) !== null)
。
我不知道我的解决方案的性能或优雅程度,但这是我正在使用的方法:
if (preg_match('/^[\[\{]\"/', $string)) {
$aJson = json_decode($string, true);
if (!is_null($aJson)) {
... do stuff here ...
}
}
由于我所有的JSON编码字符串都以{“开头,因此足以使用RegEx进行测试。我对RegEx一点都不流利,因此可能有更好的方法来做到这一点。另外:strpos()可能更快。
只是想让我的钱值得。
PS刚刚将RegEx字符串更新为/^[\[\{]\"/
,还可以找到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;
}
单元测试
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);
}
}
ErrorException
字符串是数组还是对象。
扩展此答案如何处理:
<?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,如果解码正确,则将其返回,请注意性能的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 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;
}
资源资源
如果需要成功的解码数据,则可以使用与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)
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));
}
对henrik的答案进行了简单的修改,即可接触到大多数所需的可能性。
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对象到PHP对象/数组:
/**
* If $value is a JSON encoded object or array it will be decoded
* and returned.
* If $value is not JSON format, then it will be returned unmodified.
*/
function get_data( $value ) {
if ( ! is_string( $value ) ) { return $value; }
if ( strlen( $value ) < 2 ) { return $value; }
if ( '{' != $value[0] && '[' != $value[0] ) { return $value; }
$json_data = json_decode( $value );
if ( ! $json_data ) { return $value; }
return $json_data;
}
这是我创建的一个高性能且简单的函数(在使用前使用基本的字符串验证 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;
}
json_decode
一次...,还要检查的输入和返回值json_decode
。