PHPで文字列がJSONかどうかを確認する最も速い方法は?


385

文字列がJSONかどうかを確認する本当に高速な方法が必要です。私はこれが最善の方法ではないと感じています:

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

この方法を改善したいパフォーマンス愛好家はいますか?


3
json_decode1回だけ使用することを検討してください...また、の入力値と戻り値を確認してくださいjson_decode

5
それで、どちらが答えですか?
Farid Rn

8
ここの三元スイッチは冗長です。ステートメントはすでにブール値として評価されています。
クマを1回レスリングしました。


ルイスドノバンの答えを受け入れる...それは問題なく機能しています
Poonam Bhatt

回答:


574
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}

19
誰もがこの答えを気に入っているようです。理由は何ですか?
カークウイメット

8
私は、PHP 5.3>がjson_last_error関数を使用するために必要であると信じています
Chris Harrison

97
の文字列の最初の文字{[または他のリテラルの最初の記号をチェックすると、着信文字列の多くが非JSONであると予想される場合、これを大幅に高速化できます。
Oleg

20
$ phone = '021234567'; var_dump(isJson($ phone)); 真のノーを返す!falseを返す必要があります。
VEE

23
この関数は、文字列として指定した場合でも、真の数として指定した場合でも、すべての数に対して真を返します。6.5 = true, '300' = true, 9 = trueなど。これは有効なJSON値である可能性がありますが、{}またはで有効なJSON文字列のみを確認したい場合は、関数が期待どおりに動作しない可能性があります[]
BadHorsie 14

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_errorPHP> = 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エンコード/デコード中に発生した最後のエラー(存在する場合)を返します。
Bruno

@Madanに感謝します。「json_decode」の検証により、PHP 7.0を実行していることが解決されました。
フランシスロドリゲス

確かにjson_decodeはリテラルfalseに対してfalseを返すだけなので、((strlen($json) === 5) && ($json !== 'false'))そのエッジを回避するためにチェックも行う必要がありますか?
MrMesees 2017

@Bruno最後のデコードがエラーなしで機能する場合は、をjson_last_error返しますJSON_ERROR_NONE
Andrea

80

あなたが本当にする必要があるのはこれだけです...

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

このリクエストは、別の機能を必要としません。is_objectをjson_decodeで囲み、次に進んでください。このソリューションでは、人々があまりに多くのことを考えすぎているようです。


1
配列は、単純な配列の場合RomanM.Kosだけでは、明確にするために、@、次にあなたが使用する必要があるis_arrayに加えてis_object、他の、is_objectJSONとしてエンコード単純な配列のために偽を返します。したがって、この場合は@ggutenbergが適切です。true引数を渡すと、json_decodeオブジェクトが配列として返されます。理論的には常にデコードを配列に強制し、をチェックするだけis_arrayで動作します。
userabuser 2014

@userabuserもし私json_encode($array)が単純なPHP配列の場合json_decode($str)は、オブジェクトを受け取りますが配列は受け取りません。json_decode($str, true)強制的に配列に変換します。コードで複雑な文字列を使用する理由 確認しis_array(json_decode($str, true))てしばらくすると、それを読んだときに、decodedは配列のみでなければならないことがわかります。is_object(json_decode($MyJSONArray))「ああ、ここでデコードされているかどうかを確認していますが、配列かどうか」と推測するのははるかに困難です。
ローマンM.コス

正しくはありません@ RomanM.Kosありません、codepad.viper-7.com/OFrtsq -私が言ったように、あなたは常に強制することができjson_decodeますが、オブジェクトと配列のチェックを保存するために配列を返すために、しかし、あなたがしなければないで、あなたjson_decode何最初は単純な配列でしたが、デコードではオブジェクトではなく配列を受け取ります。JSON_FORCE_OBJECT常に単純な配列を渡すIFをエンコードするようにオブジェクトを強制したい場合に使用する必要があります。
userabuser 2014

11
言うことへの反対票:This request does not require a separate function even。厳密に言えば、別の機能を必要とするソリューションはありません。関数の目的は、複数行のコードを1行のコードのように見せることではありません。関数の要点は、JSONチェックプロセスをアプリケーションのすべての場所で標準化することです。これにより、異なるプログラマー(または長期にわたって同じプログラマー)がプログラムのフローの異なる段階で異なるチェック手順を使用しなくなります。
cartbeforehorse 2014

71

json_decode「プローブ」に使用すると、実際には最速の方法ではない可能性があります。それが深くネストされた構造である場合、配列の多くのオブジェクトをインスタンス化してそれらを破棄するだけでは、メモリと時間の無駄になります。

そのため、妥当性を保証するために使用する方が速くpreg_matchRFC4627正規表現を使用できます。

  // 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はい、メモありがとうございます。しかし、ここでそれを[誤って]保持しておきましょう。そのため、実際にそれを本番環境で使用する人はいません。
マリオ2014年

1
@cartbeforehorseわかりました。ありがとう。次に、エスケープするPHPの二重引用符で囲まれた文字列コンテキストを修正しました。
マリオ2014

1
@cartbeforehorseありません。主に装飾。実際に二重にエスケープする必要があるのは、文字どおりのバックスラッシュです。\r \n \tPHPはそれらを補間するが、PCREはそれを解釈することはできませんので、それだけで理にかなっている(だけのために必要とされた/xモード)。他のオカレンスは厳密にそれを必要としません。それでも、すべての文字列PHPコンテキストで「バックスラッシュはそれ自体をエスケープします」したがって、より正確に考えることができます。
マリオ2014

4
@marioわかりました。したがって、基本的に、PHPは正規表現エンジンがバックスラッシュを見る前にバックスラッシュをエスケープします。正規表現エンジンに関する限り、文字列にはバックスラッシュの数が人間が見るものの半分です。 「reg-expはもう十分に複雑ではなかったようです」
cartbeforehorse 14

39

文字列がjson配列またはオブジェクトを表す場合、これはtrueを返します

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 2017

3
これがうまく機能するのに、なぜ他の誰もがそんなに長い間答えを持っているのですか?ありがとう。
toddmo

1
単に、素敵!「最速の方法」やパフォーマンスについてはチェックしませんでしたが、これは私がこれまでチェックしたすべてのケースをカバーしています。これは、悪名高いことわざ「大槌を使ってナッツを割るな」の典型的な例です。プログラマーの観点からは、コードを単純で短く、理解しやすい状態に保つことが常に優れています。パフォーマンスと単純さは、このスレッドの範囲外のもう1つの議論です。
Fr0zenFyr

これはきちんとしたロジックですが、空の配列に対してfalseを返すことにも注意してください。次に例を示しますvar_dump(isJson('[]')); // bool(false)。ブール値に関するドキュメントによると、これはPHPがゼロ要素の配列をfalseと評価するためです。以下は、returnステートメントを調整するための小さな修正です。それはこのケースを処理する復号化出力に同一の比較を行う:return $json !== false && $str != $json;
j13k

@ j13k同一の比較はisJson('hello')trueに評価されますが、これは有効な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または無効なjsonでない場合、json_decode()はNULLを返すため です


JSONを検証する単純な関数

JSONを複数の場所で検証する必要がある場合は、いつでも次の関数を使用できます。

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

上記の関数では、それが有効なJSONである場合にtrueを返します。


3
json_decode('null') == NULLそしてnull、有効なJSON値です。
zzzzBov 2015年

「null」がjson.parser.onlineで有効なjsonかどうかをテストしましたが、有効なjsonではないようです。また、json_decode()はjsonを検証するためのphpコア関数なので、出力で誤った結果が得られることはないと思います。
Mohammad Mursaleen、2015年

検証されていないWebサイトを信頼するのではなく、仕様に同意しないことを検討してください(2ページ)。または、JSON.parse('null')開発コンソールで試してください。
zzzzBov 2015年

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

無効なエンコーディングが検出された場合、http://tr.php.net/manual/en/function.json-decode.phpの戻り値はnullです。


4
また、「null」に対してnullを不適切に返します(これは有効なJSONではありませんが、それ以外の場合はjson_decodeに対して完全に「有効」になる場合があります)。図を行きます。

私はこれがそうであると思います:json_decode($str)!=null;そうでなければ関数は呼び出されるべきis_not_jsonです
ヨシ

その関数は、「JSON以外のものです」という名前に変更する方がよいでしょう。
lonesomeday

2
@ user166390 json_decode('null')は仕様に従って有効なJSONであり、の値を返す必要がありますnull
zzzzBov 2015年

また、このメソッドis_json('false')を使用is_json('[]')するとfalse、タイプがチェックされないために返されることにも注意してください。このメソッドはむしろ戻るべきだと思います$str === null || json_decode($str) !== null
Antoine Pinsard

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 2014

しかし'0'、有効なjsonではありません...なぜ私は警戒するのですか?@Kzqai
14

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ます。

この動作を確認するには、次の2つの例を確認してください。


"hello"は有効なJSONであり、オブジェクトでも配列でもないjson_last_error()だけで十分です
JoniJnm

1
json_last_error()文字列を指定4するとjson_decode()、エラーコードが返されます"hello"。ここの例:3v4l.org/lSsEo
Lewis Donovan

あなたのコードは、間違っている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

以前、私はnull値をチェックしていましたが、これは実際には間違っていました。

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

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 2014

@Chaoixを使用json_decode($str,true)すると、オブジェクトが配列に変換されるため、is_arrayチェックに合格します。ただし、文字列、整数などについては修正します。
ポールフィリップス

json_encodeの2番目のパラメーターの意味を理解しています。@Ahad Aliの解決策は、タイピングと、アルゴリズムで一度だけjson_decodeを実行するという点ではるかに優れていると私はまだ思います。
Chaoix 2015年

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

3

これらの解決策のいくつかを試しましたが、何もうまくいきませんでした。私はこの簡単なことを試します:

$isJson = json_decode($myJSON);

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

2番目のパラメーターなしの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)です。


とても素敵です:)感心します
Mahdi

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

単体テスト

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よりも速いと想像しますが、誰かがこの仮定でバックアップしてくれれば、私はこれについての考えを感謝します。
マーク

それは運賃論です。関係する処理時間はわかりませんが、処理時間が速い場合はそうです。
セブンアース

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が配列またはオブジェクトを表す必要があるという(誤った)信念にも賛成しています。この答えは他の30ダースの答えと何か違うことをしていますか?
miken32 2018

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

最速の方法かもしれない PHPオブジェクト/アレイへの可能なJSONオブジェクトをデコード:

/**
 * 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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.