Самый быстрый способ проверить, является ли строка JSON в PHP?

385

Мне нужен действительно очень быстрый способ проверки, является ли строка JSON или нет. Я чувствую, что это не лучший способ

function isJson($string) {
    return ((is_string($string) &&
            (is_object(json_decode($string)) ||
            is_array(json_decode($string))))) ? true : false;
}

Любые энтузиасты производительности хотят улучшить этот метод?

Кирк Уймет
источник
3
Рассмотрите возможность использования только json_decodeодин раз ... также проверьте входные и возвращаемые значения json_decode.
5
Итак, какой ответ?
Фарид Rn
8
Тройной выключатель здесь избыточен. Ваше утверждение уже оценивается как логическое значение.
Я боролся с медведем один раз.
Примите ответ Льюиса Донована ... он работает нормально
Poonam Bhatt

Ответы:

574
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}
Хенрик П. Хессель
источник
19
Похоже, что всем нравится этот ответ. Любое объяснение почему?
Кирк Уймет
8
Я считаю, что PHP 5.3> необходим для использования функции json_last_error
Крис Харрисон
97
Проверка первого символа строки для {, [или первого символа любого другого литерала потенциально может значительно ускорить эту вверх , когда многие из входящих строк , как ожидается , будут не-JSON.
Олег В. Волков
20
$ phone = '021234567'; var_dump (isJson ($ телефон)); верни истину нет! он должен вернуть false.
ви
23
Осторожно, эта функция будет возвращать true для любого числа, независимо от того, указали ли вы его в виде строки или истинного числа. 6.5 = true, '300' = true, 9 = trueи т. д. Таким образом, это может быть допустимым значением JSON, но функция может работать не так, как вы ожидаете, если вы хотите проверять только допустимые строки JSON с помощью {}или [];
BadHorsie
156

Ответ на вопрос

Функция 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 действителен, но предыдущий декодированный недействителен, ваш код будет работать правильно, потому что: « Возвращает последнюю ошибку (если есть), возникшую во время последнего кодирования / декодирования JSON. »
Бруно,
Спасибо @Madan, проверка «json_decode» решила, что я использую PHP 7.0.
Фрэнсис Родригес
Конечно, json_decode может просто вернуть false для буквального false, поэтому ((strlen($json) === 5) && ($json !== 'false'))следует также проверить, чтобы избежать этого края?
MrMesees
@Bruno Если последнее декодирование работает без ошибок, то json_last_errorвозвращается JSON_ERROR_NONE.
Андреа
80

Все, что вам действительно нужно сделать, это ...

if (is_object(json_decode($MyJSONArray))) 
{ 
    ... do something ...
}

Этот запрос не требует отдельной функции даже. Просто оберните is_object вокруг json_decode и двигайтесь дальше. Кажется, что это решение заставляет людей слишком много думать об этом.

user1653711
источник
1
@ RomanM.Kos Просто для ясности, если массив является простым массивом, вам нужно использовать is_arrayв дополнение к is_object, иначе is_objectбудет возвращать false для простых массивов, закодированных в виде JSON. Так что @ggutenberg прав в этом случае. Передача истинного аргумента json_decodeпринудительно возвращает объект в виде массива. Теоретически вы всегда можете принудительно декодировать массив и просто проверить is_array, что должно работать.
userabuser
@userabuser Если я json_encode($array)для простого массива PHP, а затем json_decode($str)я получу объект, но не массив. json_decode($str, true)заставляет конвертировать в массив. Почему сложная строка в вашем коде? Проверьте is_array(json_decode($str, true))и через некоторое время, прочитав его, вы поймете, что декодированный должен быть только массив. Гораздо сложнее догадаться is_object(json_decode($MyJSONArray))"О, вот я проверяю, является ли декодированный массив или нет?"
Роман М. Косс
@ RomanM.Kos Нет, это не правильно, codepad.viper-7.com/OFrtsq - как я уже говорил, вы всегда можете заставить json_decodeвернуть массив , чтобы сохранить вас для проверки объекта и массива, но если вы этого не сделаете и вы , json_decodeчто для начала, это был простой массив, в ответ вы получите массив при декодировании, а не объект. Вы должны использовать, JSON_FORCE_OBJECTесли вы хотите всегда принудительно вызывать объект для кодирования IF, передавая простой массив.
userabuser
11
Downvote за слово: This request does not require a separate function even. Строго говоря, ни одно решение не требует отдельной функции. Смысл функции не в том, чтобы несколько строк кода выглядели как одна строка кода. Смысл этой функции заключается в том, чтобы сделать процесс проверки JSON стандартом повсюду в вашем приложении, чтобы разные программисты (или один и тот же программист с течением времени) не использовали разные процедуры проверки на разных этапах выполнения программы.
верховая езда
71

Использование 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));

Однако здесь недостаточно энтузиаста производительности, чтобы беспокоиться о тестах.

марио
источник
11
Выполните рекурсивное регулярное выражение для проверки JSON здесь: stackoverflow.com/questions/2583472/regex-to-validate-json/… - Но оказывается, что PHP json_decodeвсегда быстрее, чем регулярное выражение PCRE. (Хотя он не очень оптимизирован, синтетические тесты не найдены и могут вести себя по-другому в Perl ..)
mario
3
@vee Да, спасибо за примечание. Но давайте оставим это здесь [неправильно], чтобы никто не использовал это в производстве.
Марио
1
@cartbeforehorse Хорошо, спасибо. Тогда я исправил выходящий полезный для PHP контекст двойных кавычек.
Марио
1
@cartbeforehorse Это не так. В основном украшения. Это просто буквальный обратный слеш, который действительно требует двойного побега. Для \r \n \tэто имеет смысл только поэтому PHP не интерполировать их, но пусть PCRE интерпретировать их (только требуется для /xрежима). Другие случаи не нуждаются в этом строго; и все же «обратная косая черта избегает себя» во всех строковых контекстах PHP. Так что можно считать это более точным.
Марио
4
@ mario Хорошо, понятно. В общем, PHP избегает обратной косой черты до того, как механизм reg-exp увидит это. Что касается механизма reg-exp, то в строке есть половина обратного слеша по сравнению с тем, что мы, люди, видим. «Подобно тому, что reg-exp уже не был достаточно сложным»
cartbeforehor
39

Это вернет 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)

Это самый короткий путь, который я могу придумать.

Сирил
источник
Вместо var_dump вы можете поместить это в тестовый пример PHPUnit. В противном случае я и удивлен, и счастлив узнать, что это правда.
MrMesees
3
Почему у всех есть такие длинные ответы, когда это прекрасно работает? Спасибо.
toddmo
1
Просто прелесть! Не проверял «самый быстрый путь» или производительность, но этот наверняка покрывает все случаи, которые я когда-либо проверял. Это классический пример печально известной пословицы «Не используйте кувалду, чтобы сломать орех» . С точки зрения программиста, всегда лучше, чтобы код был простым, коротким и легким для понимания, а производительность и простота - еще одна дискуссия, выходящая за рамки данной темы.
Fr0zenFyr
Это аккуратная логика, но также обратите внимание, что она возвращает false для пустых массивов. Например: var_dump(isJson('[]')); // bool(false). Согласно документации по логическим значениям, это происходит потому, что PHP оценивает массивы с нулевыми элементами как ложные. Вот небольшая поправка для корректировки заявления о возврате; он выполняет идентичное сравнение с декодированным выводом, который обрабатывает этот случай:return $json !== false && $str != $json;
j13k
@ j13k Идентичное сравнение оценивается isJson('hello')как истинное, что недопустимо для json. Свободное сравнение выбрано здесь специально. У меня нет быстрого решения для ситуации с пустым массивом / объектом, кроме уродливогоreturn $json == '[]' || ...
Cyril
21

Самый простой и быстрый способ, которым я пользуюсь, заключается в следующем;

$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

Если вам нужно проверить свой JSON в нескольких местах, вы всегда можете использовать следующую функцию.

function is_valid_json( $raw_json ){
    return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}

В приведенной выше функции вы получите true в ответ, если это правильный JSON.

Мухаммед Мурсалин
источник
3
json_decode('null') == NULLи nullявляется допустимым значением JSON.
zzzzBov
Я проверил, является ли 'null' допустимым json на json.parser.online, но кажется, что это недействительный json. И json_decode () - это основная функция php для проверки json, поэтому я сомневаюсь, чтобы получить какой-то неверный результат в нашем выводе.
Мохаммад Мурсалин
Вместо доверия некоторого непроверенный сайта, консультируется спецификация, которая не соглашается (стр 2) . Или попробуйте JSON.parse('null')в вашей консоли разработчика.
zzzzBov
19
function is_json($str){ 
    return json_decode($str) != null;
}

http://tr.php.net/manual/en/function.json-decode.php Возвращаемое значение равно нулю при обнаружении неверной кодировки.

АхметБ - Google
источник
4
Он также будет неправильно возвращать ноль для «ноль» (который не является допустимым JSON, но в противном случае может быть полностью «действительным» для json_decode). Пойди разберись.
Я думаю, что это должно быть: json_decode($str)!=null;или иначе функция должна быть вызвана is_not_json.
Йоши
Эту функцию лучше переименовать в «что-то иное, чем JSON»!
одинокий день
2
@ user166390, json_decode('null')является допустимым JSON в соответствии со спецификацией и должен возвращать значение null.
zzzzBov
Обратите также внимание, что с помощью этого метода is_json('false')и is_json('[]')будет возвращаться, так falseкак тип не проверяется. Я думаю, что этот метод должен скорее вернуться $str === null || json_decode($str) !== null.
Антуан Пинсард
11

Вы должны проверить введенные данные, чтобы убедиться, что передаваемая строка не пуста и фактически является строкой. Пустая строка не является допустимой 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;
}
upful
источник
+1 за то, что вы на самом деле думаете о проблеме в реальном контексте.
верховая езда
Но '0'не действует JSON ... с чего бы мне быть осторожнее? @Kzqai
upful
11

Это сделает это:

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()достаточно
JoniJnm
1
json_last_error()возвращает код ошибки, 4когда вы json_decode()строку "hello". Пример здесь: 3v4l.org/lSsEo
Льюис Донован
Ваш код неверен, helloне является допустимым JSON, но "hello"является 3v4l.org/OEJrQ
JoniJnm
9

Простой способ - проверить результат json.

$result = @json_decode($json,true);
    if (is_array($result)) {
        echo 'JSON is valid';
    }else{
        echo 'JSON is not valid';
    }
Рамез Рами
источник
6

в 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;
}
парса
источник
5

Ранее я просто проверял нулевое значение, что на самом деле было неправильно.

    $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";
Ахад Али
источник
Хорошее решение. Очень хорошо справляется с печатанием!
Chaoix
5
//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;
}
PM7Temp
источник
4

Еще один простой способ

function is_json($str)
{
    return is_array(json_decode($str,true));
}
h0mayun
источник
1
Это не правильно. Любой тип PHP может быть закодирован в JSON, например объекты, строки и т. Д., И функция json_decode должна их возвращать. Это верно только в том случае, если вы всегда декодируете массивы и не используете другие типы переменных.
Chaoix
@Chaoix using json_decode($str,true)позволяет преобразовывать объекты в массивы, чтобы он прошел проверку is_array. Вы исправляете строки, целые числа и т. Д.
Пол Филлипс
Я понимаю, что вы имеете в виду по второму параметру в json_encode. Я все еще думаю, что решение @Ahad Ali намного лучше с точки зрения набора текста и делает json_decode только один раз в ваших алгоритмах.
Chaoix
4

Нам нужно проверить, не является ли переданная строка не числовой, потому что в этом случае 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;
}
Сергей Онищенко
источник
4

Я нашел этот вопрос после того, как столкнулся с чем-то похожим в моей работе вчера. Мое решение в итоге было гибридом некоторых из подходов выше:

function is_JSON($string) {

  $String_Is_JSON = (is_null(json_decode($string, TRUE))) ? FALSE : TRUE;

  return $String_Is_JSON;
}
Rounin
источник
3

Я пробовал некоторые из этих решений, но у меня ничего не получалось. Я пробую эту простую вещь:

$isJson = json_decode($myJSON);

if ($isJson instanceof \stdClass || is_array($isJson)) {
   echo("it's JSON confirmed");
} else {
   echo("nope");
}

Я думаю, что это хорошее решение, так как декодирование JSON без второго параметра дает объект.

РЕДАКТИРОВАТЬ: Если вы знаете, что будет вход, вы можете адаптировать этот код для ваших нужд. В моем случае я знаю, что у меня есть Json, начинающийся с "{", поэтому мне не нужно проверять, является ли он массивом.

Греко Джонатан
источник
Ваш JSON потенциально может быть просто массивом, и в этом случае это будет массив, а не stdClass $ foo = "[1, 1, 2, 3]"; var_dump (json_decode ($ Foo)); => array (4) {[0] => int (1) [1] => int (1) [2] => int (2) [3] => int (3)}
Миша Наследов,
3

Используя 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, - это вернуться json_decode($json, true) !== null).

Мэтью Андерсон
источник
очень приятно :) я восхищаюсь тобой
Махди
2

Я не знаю о производительности или элегантности моего решения, но это то, что я использую:

if (preg_match('/^[\[\{]\"/', $string)) {
    $aJson = json_decode($string, true);
    if (!is_null($aJson)) {
       ... do stuff here ...
    }
}

Поскольку все мои строки в кодировке JSON начинаются с {", достаточно проверить это с помощью RegEx. Я не очень хорошо разбираюсь в RegEx, поэтому может быть лучший способ сделать это. Также: strpos () может быть быстрее.

Просто пытаюсь отдать в мою цену.

PS Просто обновил строку RegEx, /^[\[\{]\"/чтобы также найти строки массива JSON. Так что теперь он ищет либо [", либо {" в начале строки.

maxpower9000
источник
2

Должно быть что-то вроде этого:

 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если строка является массивом или объектом.
Sykez
1

Расширяя этот ответ Как насчет следующего:

<?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);
?>
Sevenearths
источник
1
Не следует ли выполнить проверку подстроки перед выполнением декодирования, чтобы сэкономить время, если в этой проверке обнаружена ошибка? Я бы предположил, что 4 проверки подстрок будут быстрее, чем json_decode, но если кто-то сможет поддержать меня с этим предположением, я буду признателен за любые мысли по этому поводу.
Марк
Это тарифный аргумент. Я не знаю время обработки, но если оно быстрее, то да.
Семь Земель
1

Привет, вот небольшой фрагмент из моей библиотеки, в этом первом условии я просто проверяю, являются ли данные 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
    }
}
Джек
источник
На этот вопрос было отправлено 34 ответа, многие из которых также поддерживают (ошибочное) убеждение, что JSON должен представлять массив или объект. Этот ответ чем-то отличается от других 3-х десятков ответов?
miken32
1

Еще одно предложение от меня :)

function isJson(string $string) {
  return ($result = json_decode($string, true)) ? $result : $string;
}
kalicki2k
источник
0

Пользовательская функция

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;

}

Ресурсы

https://gist.github.com/rafasashi/93d06bae83cc1a1f440b

RafaSashi
источник
0

Недавно сделанная функция для совместимости с 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)
biziclop
источник
0
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));
}
GONZO
источник
2
@ использовать для отладки (скрывать ошибку), но это абсолютно не рекомендуется
aswzen
0

Простая модификация ответа Генрика, чтобы коснуться наиболее необходимых возможностей.

(включая "{} и []")

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;

}

источник
0

Самый быстрый способ, возможно, декодировать возможный объект 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;
}
Philipp
источник
0

Вот эффективная и простая функция, которую я создал (которая использует базовую проверку строк перед использованием 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;
}

источник