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

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

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

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

+335
источник поделиться
29 ответов
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}
+515
источник

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

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

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

+142
источник
другие ответы

Связанные вопросы


Похожие вопросы

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

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

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

+71
источник

Используя 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
источник

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

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

+29
источник

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

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

+19
источник
function is_json($str){ 
    return json_decode($str) != null;
}

http://tr.php.net/manual/en/function.json-decode.php возвращаемое значение равно null, когда обнаружена некорректная кодировка.

+17
источник

Вы должны подтвердить свой ввод, чтобы убедиться, что строка, которую вы передаете, не является пустой и является, фактически, строкой. Пустая строка недействительна 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;
}
+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 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.

Чтобы увидеть это в действии, проверьте эти два примера:

+8
источник

Простым методом является проверка результата json.

$result = @json_decode($json,true);
    if (is_array($result)) {
        echo 'JSON is valid';
    }else{
        echo 'JSON is not valid';
    }
+7
источник

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

    $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
источник

в 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
источник

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

function is_json($str)
{
    return is_array(json_decode($str,true));
}
+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
источник

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

$isJson = json_decode($myJSON);

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

Я думаю, что это прекрасный solutiuon, поскольку декодирование JSON без второго параметра дает объект.

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

+3
источник

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

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

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

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

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

+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
источник

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

 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);
    }
}
+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 definitely JSON
    }
}
+1
источник

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

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));
}
0
источник

Простая модификация для 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;

}
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 linting. Я предпочитаю использовать https://github.com/Seldaek/jsonlint, который не возвращает ложные позитивы, упомянутые выше.

0
источник

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

function isJson(string $string) {
  return ($result = json_decode($string, true)) ? $result : $string;
}
0
источник
if(!empty(json_decode($data)))
{
echo "real json";
}
-2
источник

проверьте его с помощью этой функции:

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;
  }
}
-2
источник

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);
}
-2
источник

Посмотрите другие вопросы по меткам или Задайте вопрос