Мне нужен действительно быстрый метод проверки, является ли строка 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.
Полная программа для проверки точной ОШИБКИ
Всегда хорошо знать точную ошибку во время разработки. Вот полная программа для проверки точной ошибки на основе документов 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
}
Надеюсь, это полезно. Счастливое кодирование!
Все, что вам действительно нужно сделать, это...
if (is_object(json_decode($MyJSONArray)))
{
... do something ...
}
Этот запрос не требует отдельной функции. Просто заверните is_object вокруг json_decode и перейдите. Кажется, у этого решения есть люди, которые слишком много думают о нем.
is_array
в дополнение к is_object
, иначе is_object
вернет false для простых массивов, закодированных как JSON. Так что @ggutenberg прав в этом случае. Передача истинного аргумента в json_decode
вынуждает объект возвращаться как массив. Теоретически вы всегда можете принудительно декодировать массив и просто проверять is_array
, это должно работать.
Используя json_decode
для "зондирования", это может быть не самый быстрый способ. Если это глубоко вложенная структура, то создание множества объектов массивов, чтобы просто выбросить их, является пустой тратой памяти и времени.
Таким образом, может быть быстрее использовать preg_match
и RFC4627 regex, чтобы гарантировать достоверность:
// 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));
Недостаточно энтузиаста производительности, чтобы беспокоиться о контрольных показателях здесь.
(?R)
регулярного выражения, выполнимого, но, похоже, никто еще не пытался это сделать.
Это вернет 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)
Это самый короткий способ, с которым я могу придумать.
function is_json($str){
return json_decode($str) != null;
}
http://tr.php.net/manual/en/function.json-decode.php возвращаемое значение равно null, когда обнаружена некорректная кодировка.
json_decode($str)!=null;
или иначе функция должна называться is_not_json
.
Вы должны подтвердить свой ввод, чтобы убедиться, что строка, которую вы передаете, не является пустой и является, фактически, строкой. Пустая строка недействительна 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'
(строка нуля) пуста по логике php ...
Самый простой и быстрый способ, которым я пользуюсь, - следовать;
$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_decode() возвращает NULL, если введенная строка не json или недействительна json.
Если вы должны проверить свой JSON в нескольких местах, вы всегда можете использовать следующую функцию.
function is_valid_json( $raw_json ){
return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}
В приведенной выше функции вы вернетесь взамен, если это действительный JSON.
json_decode('null') == NULL
и null
является допустимым значением JSON.
Простым методом является проверка результата json.
$result = @json_decode($json,true);
if (is_array($result)) {
echo 'JSON is valid';
}else{
echo 'JSON is not valid';
}
Это сделает это:
function isJson($string) {
$decoded = json_decode($string);
if ( !is_object($decoded) && !is_array($decoded) ) {
return false;
}
return (json_last_error() == JSON_ERROR_NONE);
}
if ( isJson($someJsonString) ) {
echo "valid JSON";
} else {
echo "not valid JSON";
}
в 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;
}
Нам нужно проверить, не является ли принятая строка не числовой, потому что в этом случае 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;
}
Раньше я просто проверял нулевое значение, что было неправильно.
$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 JSON confirmed");
} else {
echo("nope");
}
Я думаю, что это прекрасный solutiuon, поскольку декодирование JSON без второго параметра дает объект.
EDIT: Если вы знаете, какой будет вход, вы можете адаптировать этот код к вашим потребностям. В моем случае я знаю, что у меня есть 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;
}
Unit тест
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);
}
}
Развернуть этот ответ Как насчет следующего:
<?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);
?>
Я не знаю о производительности или элегантности моего решения, но это то, что я использую:
if (preg_match('/^[\[\{]\"/', $string)) {
$aJson = json_decode($string, true);
if (!is_null($aJson)) {
... do stuff here ...
}
}
Поскольку все мои закодированные строки JSON начинаются с { ", достаточно проверить это с помощью RegEx.Я совсем не уверен в RegEx, поэтому может быть лучший способ сделать это. Также: strpos() может быть быстрее.
Просто пытаясь дать мне свою ценность.
P.S. Просто обновите строку RegEx до /^[\[\{]\"/
, чтобы найти строки массива JSON. Поэтому теперь он ищет либо [ ", либо {" в начале строки.
следует рассмотреть некоторые более сложные методы json linting. Я предпочитаю использовать https://github.com/Seldaek/jsonlint, который не возвращает ложные позитивы, упомянутые выше.
Самый быстрый способ, возможно, декодировать возможный объект 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;
}
Простая модификация для 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;
}
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));
}
Свежеприготовленная функция для совместимости с 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 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;
}
Ресурсы
проверьте его с помощью этой функции:
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;
}
}
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 миллиона раз повторения, поэтому она не слишком коротка в любом случае
изменить: после некоторых мыслей я предпочитаю это;
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";
}
json_decode
один раз ... также проверьте входные и возвращаемые значенияjson_decode
.