Cara tercepat untuk memeriksa apakah string JSON di PHP?

385

Saya membutuhkan metode yang sangat, sangat cepat untuk memeriksa apakah sebuah string adalah JSON atau tidak. Saya merasa ini bukan cara terbaik:

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

Adakah penggemar kinerja di luar sana yang ingin meningkatkan metode ini?

Kirk Ouimet
sumber
3
Pertimbangkan hanya menggunakan json_decodesekali ... juga, periksa input dan kembalikan nilai json_decode.
5
Jadi, yang mana jawabannya?
Farid Rn
8
Saklar ternary di sini berlebihan. Pernyataan Anda sudah dievaluasi sebagai boolean.
Aku pernah bergulat dengan beruang.
Terima jawaban Lewis Donovan ... itu berfungsi dengan baik
Poonam Bhatt

Jawaban:

574
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}
Henrik P. Hessel
sumber
19
Sepertinya semua orang menyukai jawaban ini. Adakah penjelasan mengapa?
Kirk Ouimet
8
Saya percaya PHP 5.3> diperlukan untuk menggunakan fungsi json_last_error
Chris Harrison
97
Memeriksa karakter pertama dari string {, [atau simbol pertama dari literal lain berpotensi sangat mempercepat ini ketika banyak string yang masuk diharapkan bukan JSON.
Oleg V. Volkov
20
$ phone = '021234567'; var_dump (isJson ($ phone)); mengembalikan true no! itu harus kembali salah.
vee
23
Hati-hati, fungsi ini juga akan mengembalikan nilai true untuk nomor apa pun, apakah Anda menetapkannya sebagai string atau angka sebenarnya. 6.5 = true, '300' = true, 9 = truedll. Jadi ini mungkin nilai JSON yang valid tetapi fungsinya mungkin tidak berperilaku seperti yang Anda harapkan, jika Anda ingin memeriksa hanya untuk string JSON yang valid dengan {}atau [];
BadHorsie
156

Jawab pertanyaan

Fungsi json_last_errormengembalikan kesalahan terakhir yang terjadi selama JSON encoding dan decoding. Jadi cara tercepat untuk memeriksa JSON yang valid adalah

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

Catatan yang json_last_errordidukung dalam PHP> = 5.3.0 saja.

Program lengkap untuk memeriksa GALAT yang tepat

Itu selalu baik untuk mengetahui kesalahan yang tepat selama waktu pengembangan. Berikut ini adalah program lengkap untuk memeriksa kesalahan yang sebenarnya berdasarkan pada dokumen 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;
}

Menguji dengan INPUT JSON Valid

$json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
$output = json_validate($json);
print_r($output);

OUTPUT yang valid

Array
(
    [0] => stdClass Object
        (
            [user_id] => 13
            [username] => stack
        )

    [1] => stdClass Object
        (
            [user_id] => 14
            [username] => over
        )
)

Menguji dengan JSON yang tidak valid

$json = '{background-color:yellow;color:#000;padding:10px;width:650px;}';
$output = json_validate($json);
print_r($output);

OUTPUT tidak valid

Syntax error, malformed JSON.

Catatan tambahan untuk (PHP> = 5.2 && PHP <5.3.0)

Karena json_last_errortidak didukung dalam PHP 5.2, Anda dapat memeriksa apakah penyandian atau decoding mengembalikan boolean FALSE. Berikut ini sebuah contoh

// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
    // JSON is invalid
}

Semoga ini bermanfaat. Selamat Coding!

Madan Sapkota
sumber
Sedikit presisi: jika json ini valid tetapi yang didekodekan sebelumnya tidak valid, kode Anda akan berfungsi dengan benar, karena: " Mengembalikan kesalahan terakhir (jika ada) terjadi selama pengkodean / decoding JSON terakhir . "
Bruno
Terima kasih @Madan, verifikasi "json_decode" memecahkan saya bahwa saya menjalankan PHP 7.0.
Francis Rodrigues
Tentunya json_decode bisa saja mengembalikan false untuk false literal, jadi pemeriksaan ((strlen($json) === 5) && ($json !== 'false'))juga harus dilakukan untuk menghindari kelebihan itu?
MrMesees
@ Bruno Jika decoding terakhir bekerja tanpa kesalahan maka json_last_errorkembali JSON_ERROR_NONE.
Andrea
80

Yang perlu Anda lakukan hanyalah ini ...

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

Permintaan ini bahkan tidak memerlukan fungsi terpisah. Bungkus is_object sekitar json_decode dan lanjutkan. Tampaknya solusi ini membuat orang terlalu memikirkannya.

pengguna1653711
sumber
1
@ RomanM.Kos Hanya untuk menjadi jelas, jika array adalah array sederhana, maka Anda perlu menggunakan is_arrayselain itu is_object, yang lain is_objectakan mengembalikan false untuk array sederhana yang dikodekan sebagai JSON. Jadi @ggutenberg benar dalam hal ini. Melewati argumen yang benar untuk json_decodememaksa objek untuk dikembalikan sebagai array. Secara teori Anda selalu dapat memaksa decode ke array dan hanya memeriksa is_array, itu harus bekerja.
userabuser
@userabuser Jika saya json_encode($array)untuk array PHP sederhana, dan kemudian json_decode($str)saya akan menerima objek, tetapi tidak array. json_decode($str, true)memaksa untuk mengkonversi menjadi array. Mengapa string rumit dalam kode Anda? Periksa is_array(json_decode($str, true))dan beberapa saat kemudian ketika Anda membacanya, Anda akan memahami bahwa yang diterjemahkan hanya array. Jauh lebih sulit untuk ditebak, is_object(json_decode($MyJSONArray))"Oh, di sini saya memeriksa decode apakah array atau tidak?"
Roman M. Koss
@ RomanM.Kos Tidak, itu tidak benar, codepad.viper-7.com/OFrtsq - seperti yang saya katakan, Anda selalu dapat memaksa json_decodeuntuk mengembalikan array untuk menyelamatkan Anda memeriksa objek dan array, tetapi jika Anda tidak DAN Anda json_decodeapa adalah larik sederhana untuk memulai, Anda akan menerima larik sebagai imbalan atas dekode, bukan objek. Anda harus menggunakan JSON_FORCE_OBJECTjika Anda ingin selalu memaksa objek pada encode JIKA melewati array sederhana.
userabuser
11
Downvote untuk mengatakan: This request does not require a separate function even. Sebenarnya, tidak ada solusi yang membutuhkan fungsi terpisah. Maksud suatu fungsi bukan untuk membuat beberapa baris kode terlihat seperti satu baris kode. Maksud dari fungsi ini adalah untuk membuat standar proses pengecekan JSON di mana-mana dalam aplikasi Anda, sehingga programmer yang berbeda (atau programmer yang sama dari waktu ke waktu) tidak menggunakan prosedur pemeriksaan yang berbeda pada tahap yang berbeda dalam aliran program.
cartbeforehorse
71

Menggunakan json_decode untuk "menyelidiki" itu mungkin sebenarnya bukan cara tercepat. Jika itu adalah struktur yang sangat bersarang, maka instantiasi banyak objek array untuk membuangnya adalah membuang-buang memori dan waktu.

Jadi mungkin lebih cepat untuk digunakan preg_matchdan regex RFC4627 juga memastikan validitas :

  // in JS:
  var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
         text.replace(/"(\\.|[^"\\])*"/g, '')));

Hal yang sama di PHP:

  return !preg_match('/[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]/',
       preg_replace('/"(\\.|[^"\\\\])*"/', '', $json_string));

Namun, tidak cukup penggila kinerja yang peduli dengan tolok ukur di sini.

mario
sumber
11
Selesaikan regex rekursif untuk memverifikasi JSON di sini: stackoverflow.com/questions/2583472/regex-to-validate-json/… - Tetapi ternyata PHP json_decodeselalu lebih cepat daripada regre PCRE. (Meskipun itu tidak sangat dioptimalkan, tidak ada tes sintetis yang ditemukan, dan mungkin berperilaku berbeda di Perl ..)
mario
3
@vee Ya, terima kasih atas catatannya. Tapi mari kita simpan di sini [salah], jadi tidak ada yang benar-benar menggunakannya dalam produksi.
mario
1
@cartbeforehorse Oke, terima kasih. Saya memperbaiki yang bermanfaat untuk PHPs string string dikutip ganda kemudian.
mario
1
@cartbeforehorse Tidak. Sebagian besar dekorasi. Hanya backslash literal yang memang membutuhkan pelarian ganda. Untuk \r \n \titu hanya masuk akal sehingga PHP tidak menginterpolasi mereka, tetapi biarkan PCRE menafsirkannya (hanya diperlukan untuk /xmode). Kejadian lain tidak sepenuhnya membutuhkannya; namun masih "backslash lolos sendiri" di semua konteks PHP string. Jadi orang bisa menganggapnya lebih tepat.
mario
4
@ Mario Oke, saya mengerti. Jadi pada dasarnya, PHP lolos dari garis miring terbalik sebelum mesin reg-exp melihatnya. Sejauh menyangkut mesin reg-exp, ada setengah jumlah backslash dalam string seperti yang kita manusia lihat. "Seperti reg-exp sudah tidak cukup rumit"
cartbeforehorse
39

Ini akan mengembalikan true jika string Anda mewakili json array atau objek :

function isJson($str) {
    $json = json_decode($str);
    return $json && $str != $json;
}

Ini menolak string json yang hanya berisi angka, string atau boolean, meskipun string tersebut secara teknis valid 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)

Ini adalah cara terpendek yang bisa saya lakukan.

Cyril
sumber
Daripada var_dump, Anda bisa memasukkan ini ke dalam uji kasus PHPUnit. Kalau tidak, saya sama-sama terkejut dan senang mengetahui itu benar.
MrMesees
3
Mengapa semua orang memiliki jawaban yang panjang lebar ketika ini bekerja dengan baik? Terima kasih.
toddmo
1
Sederhana, cantik! Tidak memeriksa "cara tercepat" atau kinerja, tetapi yang satu ini pasti mencakup semua kasing yang pernah saya periksa. Ini adalah contoh klasik untuk pepatah terkenal "Jangan gunakan palu untuk memecahkan kacang" . Dari sudut pandang programmer, selalu lebih baik untuk menjaga kode tetap sederhana, pendek dan mudah dimengerti, kinerja vs kesederhanaan adalah perdebatan lain di luar cakupan utas ini.
Fr0zenFyr
Ini adalah sedikit logika yang rapi, tetapi juga perhatikan bahwa ia mengembalikan false untuk array kosong. Sebagai contoh: var_dump(isJson('[]')); // bool(false). Menurut dokumentasi tentang booleans, ini karena PHP mengevaluasi array dengan nol elemen sebagai false. Berikut ini adalah amandemen minor untuk menyesuaikan pernyataan pengembalian; ia melakukan perbandingan yang identik pada keluaran yang diterjemahkan yang menangani kasus ini:return $json !== false && $str != $json;
j13k
@ j13k Perbandingan identik bernilai isJson('hello')true, yang bukan valid json. Perbandingan longgar dipilih dengan sengaja di sini. Saya tidak punya solusi cepat untuk situasi array / objek kosong, kecuali yang jelekreturn $json == '[]' || ...
Cyril
21

Cara paling sederhana dan tercepat yang saya gunakan adalah mengikuti;

$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

Itu karena json_decode () mengembalikan NULL jika string yang dimasukkan bukan json atau json tidak valid.


Fungsi sederhana untuk memvalidasi JSON

Jika Anda harus memvalidasi JSON Anda di banyak tempat, Anda selalu dapat menggunakan fungsi berikut.

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

Dalam fungsi di atas, Anda akan mendapatkan balasan jika itu adalah JSON yang valid.

Mohammad Mursaleen
sumber
3
json_decode('null') == NULLdan nullmerupakan nilai JSON yang valid.
zzzzBov
Saya telah menguji apakah 'null' adalah json yang valid di json.parser.online tetapi tampaknya json itu tidak valid. Dan json_decode () adalah fungsi inti php untuk memvalidasi json jadi saya ragu untuk mendapatkan hasil yang salah dalam output kami.
Mohammad Mursaleen
Daripada mempercayai beberapa situs web yang tidak diverifikasi, pertimbangkan untuk berkonsultasi dengan spesifikasi, yang tidak setuju (hal 2) . Atau, coba JSON.parse('null')di konsol dev Anda.
zzzzBov
19
function is_json($str){ 
    return json_decode($str) != null;
}

http://tr.php.net/manual/en/function.json-decode.php nilai kembali adalah nol ketika terdeteksi penyandian yang tidak valid.

AhmetB - Google
sumber
4
Ini juga akan mengembalikan null secara tidak benar untuk "null" (yang bukan JSON valid, tetapi mungkin seluruhnya "valid" ke json_decode sebaliknya). Sosok pergi.
Saya pikir ini seharusnya: json_decode($str)!=null;atau fungsi harus dipanggil is_not_json.
Yoshi
Fungsi itu akan lebih baik diganti namanya "adalah sesuatu selain JSON"!
lonesomeday
2
@ user166390, json_decode('null')JSON yang valid sesuai dengan spesifikasi , dan harus mengembalikan nilai null.
zzzzBov
Harap perhatikan juga bahwa dengan metode ini is_json('false')dan is_json('[]')akan kembali falsekarena jenisnya tidak dicentang. Saya pikir metode ini sebaiknya kembali $str === null || json_decode($str) !== null.
Antoine Pinsard
11

Anda harus memvalidasi input Anda untuk memastikan string yang Anda lewati tidak kosong dan, pada kenyataannya, adalah string. String kosong bukan JSON yang valid.

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

Saya pikir dalam PHP lebih penting untuk menentukan apakah objek JSON bahkan memiliki data, karena untuk menggunakan data Anda perlu menelepon json_encode()atau json_decode(). Saya sarankan menolak objek JSON kosong sehingga Anda tidak perlu menjalankan encode dan decode pada data kosong.

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;
}
penuh
sumber
+1 untuk benar-benar memikirkan masalah dalam konteks dunia nyata.
cartbeforehorse
Tapi '0'bukan json yang valid ... kenapa aku harus waspada? @Kzqai
upful
11

Ini akan melakukannya:

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

Seperti yang ditunjukkan dalam jawaban lain, json_last_error()mengembalikan kesalahan dari json_decode terakhir kami (). Namun ada beberapa kasus penggunaan tepi di mana fungsi ini saja tidak cukup komprehensif. Misalnya, jika Anda json_decode()bilangan bulat (misalnya:) 123, atau serangkaian angka tanpa spasi atau karakter lain (misalnya:) "123",json_last_error() fungsi tidak akan menangkap kesalahan.

Untuk mengatasi ini, saya telah menambahkan langkah ekstra yang memastikan hasil dari kami json_decode()adalah objek atau array. Jika tidak, maka kami kembalifalse .

Untuk melihat ini dalam tindakan, periksa dua contoh ini:

Lewis Donovan
sumber
"hello"adalah JSON yang valid, dan itu bukan objek maupun array, json_last_error()sudah cukup
JoniJnm
1
json_last_error()mengembalikan kode kesalahan 4ketika Anda json_decode()string "hello". Contoh di sini: 3v4l.org/lSsEo
Lewis Donovan
Kode Anda salah, hellobukan JSON valid, tetapi "hello"adalah 3v4l.org/OEJrQ
JoniJnm
9

Metode yang mudah adalah dengan memeriksa hasil json ..

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

di 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;
}
Parsa
sumber
5

Sebelumnya saya hanya memeriksa nilai null, yang sebenarnya salah.

    $data = "ahad";
    $r_data = json_decode($data);
    if($r_data){//json_decode will return null, which is the behavior we expect
        //success
    }

Sepotong kode di atas berfungsi baik dengan string. Namun begitu saya memberikan nomor, itu putus. Misalnya.

    $data = "1213145";
    $r_data = json_decode($data);

    if($r_data){//json_decode will return 1213145, which is the behavior we don't expect
        //success
    }

Untuk memperbaikinya apa yang saya lakukan sangat sederhana.

    $data = "ahad";
    $r_data = json_decode($data);

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";
Ahad Ali
sumber
Solusi yang bagus. Menangani masalah pengetikan dengan sangat baik!
Chaoix
5
//Tested thoroughly, Should do the job:
public static function is_json(string $json):bool
{
    json_decode($json);
    if (json_last_error() === JSON_ERROR_NONE) {
        return true;
    }
    return false;
}
PM7Temp
sumber
4

Cara sederhana lainnya

function is_json($str)
{
    return is_array(json_decode($str,true));
}
h0mayun
sumber
1
Ini tidak benar. Setiap jenis PHP dapat dikodekan ke dalam JSON seperti objek, string, dll dan fungsi json_decode diharapkan mengembalikannya. Ini hanya benar jika Anda selalu mendekode array dan tidak ada tipe variabel lainnya.
Chaoix
@Chaoix menggunakan json_decode($str,true)membuatnya mengkonversi objek ke array sehingga akan melewati pemeriksaan is_array. Anda benar tentang string, integer, dll.
Paul Phillips
Saya melihat apa yang Anda maksud tentang parameter kedua di json_encode. Saya masih berpikir solusi @Ahad Ali adalah yang jauh lebih baik dalam hal mengetik dan hanya melakukan json_decode sekali dalam algoritma Anda.
Chaoix
4

Kita perlu memeriksa apakah string yang dikirimkan bukan numerik karena dalam kasus ini json_decode tidak menimbulkan kesalahan.

function isJson($str) {
    $result = false;
    if (!preg_match("/^\d+$/", trim($str))) {
        json_decode($str);
        $result = (json_last_error() == JSON_ERROR_NONE);
    }

    return $result;
}
Sergey Onishchenko
sumber
4

Saya menemukan pertanyaan ini setelah menemukan sesuatu yang serupa dalam pekerjaan saya, kemarin. Solusi saya pada akhirnya adalah gabungan dari beberapa pendekatan di atas:

function is_JSON($string) {

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

  return $String_Is_JSON;
}
Rounin
sumber
3

Saya sudah mencoba beberapa solusi itu tetapi tidak ada yang berhasil untuk saya. Saya mencoba hal sederhana ini:

$isJson = json_decode($myJSON);

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

Saya pikir ini solusi yang baik sejak JSON decode tanpa parameter kedua memberikan objek.

EDIT: Jika Anda tahu apa yang akan menjadi input, Anda dapat menyesuaikan kode ini dengan kebutuhan Anda. Dalam kasus saya, saya tahu saya memiliki Json yang dimulai dengan "{", jadi saya tidak perlu memeriksa apakah itu array.

Greco Jonathan
sumber
JSON Anda berpotensi hanya menjadi array, dalam hal ini akan menjadi array daripada 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)}
Misha Nasledov
3

Menggunakan PHPBench dengan kelas berikut, hasil di bawah ini dicapai:

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

Kesimpulan: Cara tercepat untuk memeriksa apakah json valid adalah kembali json_decode($json, true) !== null).

Matthew Anderson
sumber
sangat baik :) saya mengagumi Anda
Mahdi
2

Saya tidak tahu tentang kinerja atau keanggunan solusi saya, tetapi itulah yang saya gunakan:

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

Karena semua string JSON saya yang dikodekan dimulai dengan {"cukup untuk menguji untuk ini dengan RegEx. Saya sama sekali tidak fasih dengan RegEx, jadi mungkin ada cara yang lebih baik untuk melakukan ini. Juga: strpos () mungkin lebih cepat.

Hanya mencoba untuk memberikan nilai kemampuan saya.

PS Baru saja memperbarui string RegEx /^[\[\{]\"/untuk juga menemukan string array JSON. Jadi sekarang terlihat baik ["atau {" di awal string.

maxpower9000
sumber
2

Seharusnya seperti ini:

 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);
    }
}
Tinh Dang
sumber
Saya suka Anda memeriksa apakah itu sebuah string. Cocok dengan kombinasi dengan solusi pertama untuk menghindari ErrorExceptionjika string adalah array atau objek.
sykez
1

Memperluas jawaban ini Bagaimana dengan yang berikut:

<?php

    $json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
    //$json = '12';

    function isJson($string) {
        json_decode($string);
        if(json_last_error() == JSON_ERROR_NONE) {
            if(substr($string,0,1) == '[' && substr($string,-1) == ']') { return TRUE; }
            else if(substr($string,0,1) == '{' && substr($string,-1) == '}') { return TRUE; }
            else { return FALSE; }
        }
    }

    echo isJson($json);
?>
Sevenearths
sumber
1
Tidakkah pemeriksaan substring harus dilakukan sebelum mengeksekusi decode untuk menghemat waktu jika kesalahan ditemukan dalam pemeriksaan itu? Saya akan membayangkan bahwa 4 pemeriksaan substring akan lebih cepat daripada json_decode, tetapi jika seseorang dapat mendukung saya dengan asumsi ini, saya akan menghargai pemikiran tentang ini.
Tandai
Itu argumen ongkos. Saya tidak tahu waktu pemrosesan yang terlibat, tetapi jika lebih cepat maka ya.
Sevenearths
1

Hai, ini potongan kecil dari perpustakaan saya, dalam kondisi pertama ini saya hanya memeriksa apakah data json kemudian mengembalikannya jika diterjemahkan dengan benar, harap perhatikan penggunaan substr untuk kinerja (saya belum melihat file json apa pun yang tidak memulai juga oleh {atau [

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

Ada 34 jawaban yang diposting untuk pertanyaan ini, banyak di antaranya juga berlangganan kepercayaan (salah) bahwa JSON harus mewakili sebuah array atau objek. Apakah jawaban ini melakukan sesuatu yang berbeda dari 3 lusin jawaban lainnya?
miken32

1

Saran lain dari saya :)

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

0

Fungsi kustom

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

Kasing

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

}

Sumber daya

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


0

Fungsi yang baru dibuat untuk kompatibilitas PHP 5.2, jika Anda membutuhkan data yang diterjemahkan untuk sukses:

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

Pemakaian:

$json_or_not = ...;

$data = try_json_decode( $json_or_not, $success );

if( $success )
     process_data( $data );
else what_the_hell_is_it( $data );

Beberapa tes:

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
@ gunakan untuk debugging (menyembunyikan kesalahan) tetapi sama sekali tidak direkomendasikan
aswzen

0

Modifikasi sederhana untuk jawaban henrik untuk menyentuh kemungkinan yang paling diperlukan.

(termasuk "{} dan []")

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;

}

sumber
0

Cara tercepat untuk mungkin memecahkan kode objek JSON mungkin untuk PHP objek / array:

/**
 * If $value is a JSON encoded object or array it will be decoded 
 * and returned.
 * If $value is not JSON format, then it will be returned unmodified.
 */
function get_data( $value ) {
    if ( ! is_string( $value ) ) { return $value; }
    if ( strlen( $value ) < 2 ) { return $value; }
    if ( '{' != $value[0] && '[' != $value[0] ) { return $value; }

    $json_data = json_decode( $value );
    if ( ! $json_data ) { return $value; }
    return $json_data;
}
Philipp
sumber
0

Berikut ini adalah performa dan fungsi sederhana yang saya buat (yang menggunakan validasi string dasar sebelum digunakan json_decodeuntuk string yang lebih besar):

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

sumber