Найшвидший спосіб перевірити, чи є рядок 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
Отже, на яку відповідь?
Фарид Рн

8
Потрійний вимикач тут зайвий. Ваше твердження вже оцінюється як булеве.
Я боровся ведмедя одного разу.


Прийміть відповідь Льюїса Донована ... це працює чудово
Пунам Бхатт

Відповіді:


573
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 ($ телефон)); повернути справжнє ні! він повинен повернути помилкове.
віе

23
Остерігайтеся, ця функція поверне істинне для будь-якого числа, незалежно від того, вказуєте ви його як рядок або справжнє число. 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

$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 на буквальну помилку, тому ((strlen($json) === 5) && ($json !== 'false'))слід також перевірити , щоб уникнути цього краю?
MrMesees

@Bruno Якщо останнє декодування працює без помилок, то json_last_errorповертається JSON_ERROR_NONE.
Андреа

81

Все, що вам потрібно зробити, це це ...

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

Цей запит навіть не вимагає окремої функції. Просто обгорніть is_object навколо json_decode і рухайтеся далі. Здається, у цьому рішенні люди занадто багато думають над цим.


@ 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 стандартним скрізь у вашій програмі, щоб різні програмісти (або той самий програміст протягом часу) не використовували різні процедури перевірки на різних етапах потоку програми.
cartbeforehorse

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 вже не був достатньо складним"
cartbeforehorse

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
Чому всі інші мають такі довго закручені відповіді, коли це чудово працює? Дякую.
Тоддмо

1
Просто, мило! Не перевіряв на "найшвидший спосіб" чи на ефективність, але цей обов'язково охоплює всі випадки, які я коли-небудь перевіряв. Це класичний приклад для сумнозвісної приказки "Не використовуй кувалду для розламування горіха" . З точки зору програміста, завжди краще тримати код простим, коротким і легким для розуміння, продуктивність проти простоти - це ще одна дискусія поза межами цього потоку.
Fr0zenFyr

Це акуратний біт логіки, але також зауважте, що він повертає false для порожніх масивів. Наприклад: var_dump(isJson('[]')); // bool(false). Згідно з документацією про булеви, це тому, що PHP оцінює масиви з нульовими елементами як хибні. Ось незначна поправка на коригування декларації про повернення; він виконує ідентичне порівняння на декодованому виході, який обробляє цей випадок:return $json !== false && $str != $json;
j13k

@ j13k Ідентичне порівняння оцінюється isJson('hello')як істинне, що не є дійсним json. Тут вибирається вільне порівняння. У мене немає швидкого рішення для ситуації з порожнім масивом / об’єктом, крім return $json == '[]' || ...
Кирило

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.
}

У наведеній вище функції ви отримаєте істину взамін, якщо це дійсний 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 значення, що повертається, є нульовим, коли виявлено недійсне кодування.


4
Він також неправильно поверне null для "null" (що не є дійсним 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;
}

+1 за те, що насправді думає про проблему в реальному світі.
cartbeforehorse

Але '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;
}

4

Ще один простий спосіб

function is_json($str)
{
    return is_array(json_decode($str,true));
}

1
Це не правильно. Будь-який тип PHP може бути закодований в JSON, такі як об'єкти, рядки тощо, і очікується, що функція json_decode поверне їх. Це справедливо лише в тому випадку, якщо ви завжди декодуєте масиви і немає інших типів змінних.
Chaoix

@Chaoix за допомогою 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;
}

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)); => масив (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).


дуже приємно :) я захоплююсь тобою
Махді,

3

Я знайшов це питання після того, як вчора натрапив на щось подібне у своїй роботі. Моє рішення врешті-решт було гібридом деяких із підходів, наведених вище:

function is_JSON($string) {

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

  return $String_Is_JSON;
}

2

Я не знаю про продуктивність та елегантність свого рішення, але це те, що я використовую:

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

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

Просто намагаюся дати в моїй туппенсі варто.

PS Щойно оновив рядок RegEx, /^[\[\{]\"/щоб також знайти рядки масиву JSON. Отже, тепер він шукає або [", або {" на початку рядка.


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;
}

UnitTest

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);
?>

1
Чи не слід перевіряти підрядку перед виконанням декодування, щоб заощадити час, якщо в цій чеці виявлена ​​помилка? Я б міг уявити, що 4 перевірки підрядків будуть швидшими, ніж json_decode, але якщо хтось міг би підкріпити мене цим припущенням, я буду вдячний з цього приводу будь-яких думок.
Марк

Це аргумент на проїзд. Я не знаю часу на обробку, але якщо це швидше, то так.
Sevenearths

1

Привіт, ось маленький фрагмент з моєї бібліотеки. У цьому першому стані я просто перевіряю, чи дані json, і повертаю їх, якщо правильно розшифровано. Зверніть увагу на використання субстратів для продуктивності (я ще не бачив, щоб жоден файл 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;
}

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


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)

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));
}

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;
}

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.