it-swarm.com.ru

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

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

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

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

316
Kirk Ouimet
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}
496
Henrik P. Hessel

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

Функция 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
}

Надеюсь, это полезно. Удачного кодирования!

137
Madan Sapkota

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

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

69
mario

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

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

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

69
user1653711

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

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

24
Cyril
function is_json($str){ 
    return json_decode($str) != null;
}

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

16
AhmetB - Google

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

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

14
Mohammad Mursaleen

Вы должны проверить введенные данные, чтобы убедиться, что передаваемая строка не пуста и фактически является строкой. Пустая строка недопустима в формате JSON.

function is_json($string) {
  return !empty($string) && is_string($string) && is_array(json_decode($string, true)) && json_last_error() == 0;
}

Я думаю, что в PHP более важно определить, имеет ли объект JSON даже имеет data, потому что для использования данных вам нужно будет вызывать 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;
}
11
upful

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

$result = @json_decode($json,true);
    if (is_array($result)) {
        echo 'JSON is valid';
    }else{
        echo 'JSON is not valid';
    }
6
Rameez Rami

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

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";
}
6
Lewis Donovan

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

    $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";
5
Ahad Ali

в 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
Parsa

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

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

Нам нужно проверить, не является ли переданная строка не числовой, потому что в этом случае 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
Sergey Onishchenko

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

$isJson = json_decode($myJSON);

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

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

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

3
Greco Jonathan

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

 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);
    }
}
1
Tinh Dang

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

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

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

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

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

1
maxpower9000

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

<?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
Sevenearths

Недавно сделанная функция для совместимости 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
biziclop

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

function isJson(string $string) {
  return ($result = json_decode($string, true)) ? $result : $string;
}
0
kalicki2k

Привет, вот небольшой фрагмент из моей библиотеки, в этом первом условии я просто проверяю, являются ли данные 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
    }
}
0
Jack
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));
}
0
GONZO

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

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

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
RafaSashi

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

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

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
user4395445