最快的方法来检查一个string是PHP中的JSON?
我需要一个非常快速的方法来检查一个string是否是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_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中支持json_last_error
。
完整的程序来检查确切的错误
在开发期间知道确切的错误总是很好的。 这里是完整的程序来检查基于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; }
使用有效的JSONinput进行testing
$json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]'; $output = json_validate($json); print_r($output);
有效的OUTPUT
Array ( [0] => stdClass Object ( [user_id] => 13 [username] => stack ) [1] => stdClass Object ( [user_id] => 14 [username] => over ) )
使用无效的JSON进行testing
$json = '{background-color:yellow;color:#000;padding:10px;width:650px;}'; $output = json_validate($json); print_r($output);
无效的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 }
希望这是有帮助的。 快乐编码!
使用json_decode
来“探测”它实际上可能不是最快的方法。 如果它是一个深度嵌套的结构,那么实例化大量的数组对象就会丢掉内存和时间。
所以使用preg_match
和RFC4627正则expression式可能会更快,以确保有效性 :
// 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));
然而,性能爱好者不足以打扰这里的基准testing。
你真正需要做的就是这个…
if (is_object(json_decode($MyJSONArray))) { ... do something ... }
这个请求甚至不需要单独的函数。 只需将json_decode包装为is_object,然后继续。 看来这个解决scheme让人有太多的想法。
function is_json($str){ return json_decode($str) != null; }
http://tr.php.net/manual/en/function.json-decode.php检测到无效编码时返回值为空。;
你必须validation你的input,以确保你传递的string不是空的,实际上是一个string。 一个空string不是有效的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()
。 我build议否认空的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; }
如果你的string表示一个json数组或对象,这将返回true :
function isJson($str) { $json = json_decode($str); return $json && $str != $json; }
它拒绝只包含数字,string或布尔值的jsonstring,尽pipe这些string在技术上是有效的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)
这是我能想出的最短路线。
简单的方法是检查json结果..
$result = @json_decode($json,true); if (is_array($result)) { echo 'JSON is valid'; }else{ echo 'JSON is not valid'; }
另一种简单的方法
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 }
上面的代码可以很好地处理string。 但是,只要我提供号码,它就打破了。
$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'); // json error // you can enter some else condition to display success message over here
这是因为如果input的string不是json或无效的json, json_decode()将返回NULL。
我们需要检查传递的string是不是数字,因为在这种情况下,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; }
在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; }
我不知道我的解决scheme的性能或优雅,但这是我使用的:
if (preg_match('/^[\[\{]\"/', $string)) { $aJson = json_decode($string, true); if (!is_null($aJson)) { ... do stuff here ... } }
由于所有的JSON编码的string都以{“开头,所以用RegEx进行testing就足够了,我对RegEx一点也不stream行,所以可能有更好的方法来做到这一点,而且: strpos()可能会更快。
只是试图给我的婚姻价值。
PS只是将RegExstring更新为/^[\[\{]\"/
以查找JSON数组string,因此它现在在string开始处查找[”或{“)。
扩大这个答案以下内容:
<?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); ?>
自定义function
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,如果您需要解码的数据成功:
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 );
一些testing:
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; }
我已经尝试了一些解决scheme,但没有为我工作。 我尝试这个简单的事情:
$isJson = json_decode($myJSON); if ($isJson instanceof \stdClass) { echo("it's JSON confirmed"); } else { echo("nope"); }
我认为这是一个很好的解决scheme,因为JSON解码没有第二个参数给一个对象。
我试过这样的事情
<?php /* valid json */ $json1 = json_encode([ 'foo' => 'bar', 'bar', 'foo2 ' => [ 'bar' => 'foo', 'try'=> 32, 'foo', 'bar', [[[[[[]]]]]] ], 'foobar'=>[ 'foo'=>'bar', 'bar'=>'foo' ] ]); $json2 = json_encode([ 'foo' => 'bar', 'bar', 'foo2 ' => [ 'bar' => 'foo', 'try'=> 32, 'foo', 'bar', [[[[[[]]]]]] ], 'foobar'=>[ 'foo'=>'bar', 'bar'=>'foo' ] ]) . ';'; // << invalid json $mt = microtime(1); for($i=0;$i<1000000;$i++){ check1($json1); check1($json2); } echo "PROCESS TOOK: " . (microtime(1) - $mt) . " seconds\n"; $mt = microtime(1); for($i=0;$i<1000000;$i++){ check2($json1); check2($json2); } echo "PROCESS TOOK: " . (microtime(1) - $mt) . " seconds\n"; function check1($json){ return preg_match('/(?(DEFINE)(?<number>-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?)(?<boolean>true|false|null)(?<string>"([^"\\\\]*|\\\\["\\\\bfnrt\/]|\\\\u[0-9a-f]{4})*")(?<array>\[(?:(?&json)(?:,(?&json))*)?\s*\])(?<pair>\s*(?&string)\s*:(?&json))(?<object>\{(?:(?&pair)(?:,(?&pair))*)?\s*\})(?<json>\s*(?:(?&number)|(?&boolean)|(?&string)|(?&array)|(?&object))\s*))\A(?&json)\Z/six', $json); } function check2($json){ json_decode($json); return (json_last_error() === JSON_ERROR_NONE); }
产量
PROCESS TOOK: 7.5640170574188 seconds PROCESS TOOK: 4.4907619953156 seconds
正则expression式函数和本地json_decode函数之间有〜3秒的差别,但是在重复一百万次之后才会发生,因此不能太短
编辑:经过一些想法,我更喜欢这个;
if(checkjson($json)){ echo "this is json :3\n"; var_dump($json); } else { die('omg this is not json!!!'); } function checkjson(&$json){ $json = json_decode($json); return (json_last_error() === JSON_ERROR_NONE); }
if(!empty(json_decode($data))) { echo "real json"; }
用这个函数检查它:
function is_json($string) { if (is_string($string) && !is_int($string) && !is_array($string)) { json_decode($string); return (json_last_error() == JSON_ERROR_NONE); } else { return false; } }