Мне нужен действительно быстрый метод проверки, является ли строка 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_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, вы можете проверить, возвращает ли кодировка или декодирование логическое значение FALSE
. Вот пример
// decode the JSON data $result = json_decode($json); if ($result === FALSE) { // JSON is invalid }
Надеюсь, это полезно. Счастливое кодирование!
Использование 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));
Однако недостаточно энтузиастов производительности, чтобы беспокоиться о контрольных показателях.
Все, что вам действительно нужно сделать, это …
if (is_object(json_decode($MyJSONArray))) { ... do something ... }
Этот запрос не требует отдельной функции. Просто заверните is_object вокруг json_decode и перейдите. Кажется, у этого решения есть люди, которые слишком много думают об этом.
function is_json($str){ return json_decode($str) != null; }
http://tr.php.net/manual/en/function.json-decode.php Возвращаемое значение равно 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; }
Это вернет true, если ваша строка представляет собой json-массив или объект :
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)
Это самый короткий путь, который я могу придумать.
Простой метод – проверить результат 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 }
Вышеупомянутый фрагмент кода отлично работает со строками. Однако, как только я предоставляю номер, он разрывается. Например.
$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
Это потому, что json_decode () возвращает NULL, если введенная строка не json или недействительна 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; }
в 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; }
Я не знаю о производительности или элегантности моего решения, но это то, что я использую:
if (preg_match('/^[\[\{]\"/', $string)) { $aJson = json_decode($string, true); if (!is_null($aJson)) { ... do stuff here ... } }
Поскольку все мои закодированные строки JSON начинаются с {«, достаточно проверить это с помощью RegEx. Я не совсем свободно с RegEx, поэтому может быть лучший способ сделать это. Также: strpos () может быть быстрее.
Просто пытаюсь поддаться моей таппенсе.
PS Просто обновил строку RegEx до /^[\[\{]\"/
чтобы найти строки массива JSON. Теперь он ищет либо [", либо {"в начале строки.
Расширение ответа на этот вопрос. Как насчет следующего:
<?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 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)); }
Простая модификация ответа хенрика, чтобы коснуться наиболее необходимых возможностей.
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; }
Я пробовал некоторые из этих решений, но ничего не работало для меня. Я пробую эту простую вещь:
$isJson = json_decode($myJSON); if ($isJson instanceof \stdClass) { echo("it's JSON confirmed"); } else { echo("nope"); }
Я думаю, что это прекрасный solutiuon, поскольку декодирование JSON без второго параметра дает объект.
ive попробовал что-то подобное
<?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
существует ~ 3 секунды разницы между функцией регулярного выражения и функцией json_decode native, но это происходит после 1 миллиона раз повторения, поэтому она не слишком короткая в любом случае
edit: после некоторых мыслей я предпочитаю это;
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; } }