PHP bir dize JSON olup olmadığını kontrol etmenin en hızlı yolu?


385

Bir dize JSON olup olmadığını kontrol gerçekten, gerçekten hızlı bir yöntem gerekir. Bunun en iyi yol olmadığını hissediyorum:

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

Orada herhangi bir performans meraklısı bu yöntemi geliştirmek istiyor?


3
Sadece bir json_decodekez kullanmayı düşünün ... Ayrıca, giriş ve dönüş değerlerini kontrol edin json_decode.

5
Peki cevap hangisi?
Farid Rn

8
Buradaki üçlü anahtar gereksiz. İfadeniz zaten bir boole olarak değerlendiriliyor.
Bir ayı güreştim.


Lewis Donovan'ın cevabını kabul edin ... iyi çalışıyor
Poonam Bhatt

Yanıtlar:


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

19
Görünüşe göre herkes bu cevabı seviyor. Neden herhangi bir açıklama?
Kirk Ouimet

8
PHP 5.3> json_last_error işlevini kullanmak için gerekli olduğuna inanıyorum
Chris Harrison

97
İçin dizenin birinci karakteri kontrol etme {, [ya da başka bir sabitin ilk sembolü potansiyel büyük ölçüde gelen dizeleri birçok olmayan JSON olması bekleniyor zaman kadar bu bir hızlandırabilir.
Oleg V.Volkov

20
$ phone = '021234567'; var_dump (isJson ($ telefon)); geri dönüş hayır! yanlış döndürmelidir.
vee

23
Dikkat edin, bu işlev ister dize ister gerçek sayı olarak belirtilsin, herhangi bir sayı için de true değerini döndürür. 6.5 = true, '300' = true, 9 = trueBu nedenle bu geçerli bir JSON değeri olabilir, ancak yalnızca {}veya ile geçerli JSON dizelerini denetlemek istiyorsanız, işlev beklediğiniz gibi davranmayabilir [].
BadHorsie

156

Sorunun Cevabı

İşlev json_last_error, JSON kodlama ve kod çözme sırasında meydana gelen son hatayı döndürür. Geçerli JSON'u kontrol etmenin en hızlı yolu

// 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_errorYalnızca PHP> = 5.3.0 sürümlerinde desteklendiğini unutmayın .

Tam HATA kontrol etmek için tam program

Geliştirme süresi boyunca kesin hatayı bilmek her zaman iyidir. İşte PHP belgelerine dayalı tam hatayı kontrol etmek için tam bir program.

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

Geçerli JSON INPUT ile test etme

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

Geçerli ÇIKTI

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

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

Geçersiz JSON ile test etme

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

Geçersiz ÇIKTI

Syntax error, malformed JSON.

Ek not (PHP> = 5.2 && PHP <5.3.0)

Yana json_last_errorPHP 5.2 desteklenmez kodlayan veya deşifre döner boolean eğer kontrol edebilirsiniz FALSE. İşte bir örnek

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

Umarım bu yardımcı olur. Mutlu Kodlama!


Küçük hassasiyet: bu json geçerli, ancak daha önce kodu çözülmüş bir kod geçersizse, kodunuz düzgün çalışacaktır, çünkü: " Son JSON kodlama / kod çözme sırasında meydana gelen son hatayı (varsa) döndürür . "
Bruno

Teşekkürler @Madan, "json_decode" doğrulaması bana PHP 7.0 çalıştıran çözüldü.
Francis Rodrigues

Şüphesiz json_decode değişmez yanlış için sadece false ((strlen($json) === 5) && ($json !== 'false'))değerini döndürebilir, bu nedenle bu kenarı önlemek için bir kontrol de yapılmalıdır.
MrMesees

@Bruno Son kod çözme hatasız çalışıyorsa json_last_errorgeri döner JSON_ERROR_NONE.
Andrea

80

Tek yapmanız gereken bu ...

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

Bu istek ayrı bir işlev gerektirmez. Sadece is_object öğesini json_decode etrafına sarın ve devam edin. Görünüşe göre bu çözümün içinde çok fazla düşünülmüş insan var.


1
@ RomanM.Kos Sadece net olmak gerekirse, dizi basit bir dizi ise, is_arrayek olarak kullanmanız gerekir is_object, aksi is_objecttakdirde JSON olarak kodlanmış basit diziler için false döndürür. Yani @ggutenberg bu durumda haklı. Gerçek bağımsız değişkeni json_decodebir nesneye dizi olarak döndürülmeye zorlar. Teoride kod çözmeyi her zaman bir diziye zorlayabilir ve sadece kontrol etmelisiniz is_array, bu işe yaramalıdır.
userabuser

@ userabuser Eğer json_encode($array)basit PHP dizisi için i ve sonra json_decode($str)ben nesne alacak, ancak dizi alacak. json_decode($str, true)diziye dönüştürmeye zorlar. Kodunuzda neden karmaşık dize var? Kontrol edin is_array(json_decode($str, true))ve bir süre sonra okuduğunuzda, kod çözmenin sadece bir dizi olması gerektiğini anlayacaksınız. Tahmin etmek çok daha zor is_object(json_decode($MyJSONArray))"Oh, işte ben çözülüp çözülmediğini kontrol etmek için bir dizi mi değil mi?"
Roman M.Koss

Doğru değil @ RomanM.Kos Hayır, codepad.viper-7.com/OFrtsq - Dediğim gibi, her zaman zorlayabilir json_decodeEğer nesne ve dizinin kontrol kurtarmak için bir dizi dönmek için, ancak bunu yaparsanız değil VE json_decodeneyi başlamak için basit bir diziydi, kod çözme karşılığında bir dizi alacaksınız, bir nesne değil. JSON_FORCE_OBJECTBasit bir diziyi geçerek kodlamadaki bir nesneyi her zaman zorlamak istiyorsanız kullanmalısınız .
userabuser

11
Diyerek için downvote: This request does not require a separate function even. Kesin olarak, hiçbir çözüm ayrı bir işlev gerektirmez. Bir işlevin amacı , birden fazla kod satırının bir kod satırı gibi görünmesini sağlamak değildir . Fonksiyonun amacı, uygulamanızın her yerinde JSON kontrol sürecini standart hale getirmektir, böylece farklı programcılar (veya zamanla aynı programcı) program akışının farklı aşamalarında farklı kontrol prosedürleri kullanmaz.
cartbeforehorse

71

json_decode"Prob" için kullanmak aslında en hızlı yol olmayabilir. Eğer derinden iç içe geçmiş bir yapı ise, onları bir kenara atmak için çok sayıda nesne nesnesini başlatmak bellek ve zaman kaybıdır.

Bu nedenle kullanımı daha hızlı olabilir preg_matchve RFC4627 normal ifadesi de geçerliliği sağlar :

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

PHP ile aynı:

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

Ancak burada performans ölçütleriyle uğraşmak için yeterli performans meraklısı değil.


11
JSON'u burada doğrulamak için özyinelemeli regex'i tamamlayın: stackoverflow.com/questions/2583472/regex-to-validate-json/… - Ama PHP'lerin json_decodePCRE normalden daha hızlı olduğu ortaya çıkıyor . (Çok optimize olmasa da, sentetik test bulunamadı ve Perl'de farklı davranabilir.)
mario

3
@vee Evet, not için teşekkürler. Ama burada [yanlış] tutalım, bu yüzden kimse bunu üretimde kullanmıyor.
mario

1
@cartbeforehorse Tamam, teşekkürler. Ben sonra PHP çift tırnaklı dize bağlamı kaçan sağlıklı düzeltildi.
mario

1
@cartbeforehorse Öyle değil. Çoğunlukla dekorasyon. Gerçekten iki kat kaçmayı gerektiren gerçek ters eğik çizgi. Çünkü \r \n \tPHP onları enterpolasyon etmeyecek kadar mantıklı, ancak PCRE'nin bunları yorumlamasına izin verin (sadece /xmod için gerekliydi ). Diğer olaylar kesinlikle buna ihtiyaç duymaz; yine de tüm dize PHP bağlamlarında "ters eğik çizgi kaçar". Böylece kişi daha kesin olarak düşünülebilir.
mario

4
@mario Tamam, anladım. Temel olarak, reg-exp motoru görmeden önce PHP ters eğik çizgilerden kaçar. Reg-exp motoru söz konusu olduğunda, dizide insanların gördükleri gibi ters eğik çizgi sayısının yarısı vardır. "Reg-exp gibi zaten yeterince karmaşık değildi"
cartbeforehorse

39

Dizeniz bir json dizisini veya nesnesini temsil ediyorsa bu true değerini döndürür :

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

Yalnızca sayı, dize veya boole içeren json dizelerini reddeder, ancak bu dizeler teknik olarak geçerli json'dur.

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)

Gelebileceğim en kısa yol bu.


Var_dump yerine, bunu bir PHPUnit test senaryosuna koyabilirsiniz. Aksi takdirde doğru olduğunu öğrenmek için hem şaşırdım hem de mutluyum.
MrMesees

3
Bu harika çalışırken neden herkesin bu kadar uzun soluklu cevapları var? Teşekkürler.
toddmo

1
Basit bir şekilde güzel! "En hızlı yol" veya performans akıllıca kontrol etmedi ama bu emin hiç kontrol ediyorum tüm durumlarda kapsar. Bu rezil atasözü "Somun kırmak için balyoz kullanmayın" için klasik bir örnektir . Programcı bakış açısından, kodu basit, kısa ve anlaşılması kolay tutmak her zaman daha iyidir, performans ve basitlik, bu iş parçacığı için kapsam dışı bir başka tartışmadır.
Fr0zenFyr

Bu düzgün bir mantık parçasıdır, ancak boş diziler için yanlış döndürdüğünü de unutmayın. Örneğin: var_dump(isJson('[]')); // bool(false). Booleans belgelerine göre, bunun nedeni PHP'nin sıfır elemanlı dizileri yanlış olarak değerlendirmesidir. İşte dönüş ifadesini ayarlamak için küçük bir değişiklik; bu durumu ele alan kodu çözülmüş çıktı üzerinde özdeş bir karşılaştırma yapar:return $json !== false && $str != $json;
j13k

@ j13k Aynı karşılaştırma geçerli olarak değerlendirilir isJson('hello'), bu geçerli json değildir. Gevşek karşılaştırma burada amaçlanmıştır. Çirkinreturn $json == '[]' || ...
Cyril

21

Kullandığım en basit ve en hızlı yol şu şekildedir;

$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

Çünkü öyle json_decode () döner BOŞ girilen dize json veya geçersiz json değilse.


JSON'u doğrulamak için basit işlev

JSON'unuzu birden çok yerde doğrulamanız gerekiyorsa, her zaman aşağıdaki işlevi kullanabilirsiniz.

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

Yukarıdaki işlevde, geçerli bir JSON ise karşılığında true elde edersiniz.


3
json_decode('null') == NULLve nullgeçerli bir JSON değeridir.
zzzzBov

'Null' json.parser.online geçerli json olup olmadığını test ettim ama onun geçerli json değil gibi görünüyor. Ve json_decode () json doğrulamak için php çekirdek işlevi bu yüzden çıktı bazı yanlış sonuç almak için şüphe.
Mohammad Mursaleen

Doğrulanmamış bazı web sitelerine güvenmek yerine , aynı fikirde olmayan spesifikasyonlara danışmayı düşünün (sayfa 2) . Alternatif olarak, geliştirici JSON.parse('null')konsolunuzda deneyin .
zzzzBov

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

Geçersiz kodlama algılandığında http://tr.php.net/manual/en/function.json-decode.php dönüş değeri null.


4
Ayrıca, "null" için yanlış olarak null değerini döndürür (bu geçerli JSON değildir, ancak json_decode için tamamen "geçerli" olabilir). Git şekil.

Bence bu şöyle olabilir: json_decode($str)!=null;ya da başka bir şekilde işlev çağrılmalıdır is_not_json.
Yoshi

Bu işlev daha iyi adlandırılır "JSON dışında bir şey"!
lonesomeday

2
@ user166390, json_decode('null')spesifikasyona göre geçerli bir JSON'dir ve değerini döndürmelidir null.
zzzzBov

Ayrıca bu yöntemle lütfen unutmayın is_json('false')ve is_json('[]')dönecektir falsetipi işaretli olmadığından olarak. Bu yöntemin daha çok geri dönmesi gerektiğini düşünüyorum $str === null || json_decode($str) !== null.
Antoine Pinsard

11

Geçirdiğiniz dizenin boş olmadığından ve aslında bir dize olduğundan emin olmak için girişinizi doğrulamanız gerekir. Boş bir dize geçerli JSON değil.

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

PHP bu JSON nesnesi bile olmadığını belirlemek için daha önemli olduğunu düşünüyorum sahiptir verileri verilerini kullanmak için çünkü aramak gerekir, json_encode()ya da json_decode(). Boş JSON nesnelerini gereksiz yere çalıştırmamanız için boş JSON nesnelerini reddetmenizi öneririm.

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

Sorunu gerçek dünya bağlamında düşündüğünüz için +1.
cartbeforehorse

Ama '0'geçerli bir json değil ... neden dikkatli olurum? @Kzqai
upful

11

Bunu yapacak:

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

Diğer yanıtlarda gösterildiği gibi, json_last_error()son json_decode () öğemizdeki hataları döndürür. Bununla birlikte, bu fonksiyonun tek başına yeterince kapsamlı olmadığı bazı kenar kullanım durumları vardır. Örneğin, json_decode()bir tamsayı (örneğin:123 :) veya boşluk veya başka karakter içermeyen dizesi (örneğin:) "123"ise, json_last_error()işlev bir hata yakalamaz.

Bununla mücadele etmek için, sonucumuzun sonucunu sağlayan ekstra bir adım ekledim. json_decode() bir nesne veya dizi . Değilse, geri dönüyoruz false.

Bunu çalışırken görmek için şu iki örneği inceleyin:


"hello"geçerli bir JSON, ve ne bir dizi bir nesne değil json_last_error(), yeterli
JoniJnm

1
json_last_error()dize 4yaptığınızda hata kodu döndürür . Burada örnek: 3v4l.org/lSsEojson_decode()"hello"
Lewis Donovan

Kodunuz yanlış, hellogeçerli bir JSON değil "hello", 3v4l.org/OEJrQ
JoniJnm

9

Kolay yöntem json sonucunu kontrol etmektir.

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

6

içinde 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

Daha önce ben sadece aslında yanlış bir null değeri kontrol ediyordu.

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

Yukarıdaki kod parçası dizelerle iyi çalışır. Ancak sayı verir vermez, ayrılır. Örneğin.

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

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

Yaptığım şeyi düzeltmek çok basitti.

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

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";

Güzel çözüm. Yazma sorununu çok iyi ele alıyor!
Chaoix

5
//Tested thoroughly, Should do the job:
public static function is_json(string $json):bool
{
    json_decode($json);
    if (json_last_error() === JSON_ERROR_NONE) {
        return true;
    }
    return false;
}

4

Başka bir basit yol

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

1
Bu doğru değil. Herhangi bir PHP türü nesneler, dizeler vb. Gibi JSON'a kodlanabilir ve json_decode işlevinin bunları döndürmesi beklenir. Bu sadece dizilerin kodunu her zaman çözüyorsanız ve başka değişken türleri yoksa doğrudur.
Chaoix

@Chaoix kullanarak json_decode($str,true)nesneleri dizilere dönüştürür, böylece is_array kontrolünü geçecektir. Bununla birlikte, dizeleri, tamsayıları vb.
Paul Phillips

Ben json_encode ikinci parametre hakkında ne demek görmek. @Ahad Ali'nin çözümünün, algoritmalarınızda yalnızca bir kez json_decode yazmak ve yapmak açısından çok daha iyi olduğunu düşünüyorum.
Chaoix

4

Bu durumda json_decode hata yaratmadığından, iletilen dizenin sayısal olup olmadığını kontrol etmemiz gerekir.

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

    return $result;
}

4

Bu soruyu dün işimde benzer bir şeyle karşılaştıktan sonra buldum. Sonunda benim çözümüm yukarıdaki yaklaşımlardan bazılarının bir meleziydi:

function is_JSON($string) {

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

  return $String_Is_JSON;
}

3

Bu çözümlerden bazılarını denedim ama hiçbir şey benim için işe yaramıyordu. Bu basit şeyi deniyorum:

$isJson = json_decode($myJSON);

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

Ben ikinci parametre olmadan JSON kod çözme bir nesne vermek beri bu iyi bir çözüm olduğunu düşünüyorum.

EDIT: Girdi ne olacağını biliyorsanız, bu kodu ihtiyaçlarınıza göre uyarlayabilirsiniz. Benim durumumda "{" ile başlayan bir Json wich biliyorum, bu yüzden bir dizi olup olmadığını kontrol etmek gerekmez.


JSON potansiyel olarak sadece bir dizi olabilir, bu durumda stdClass $ foo = "[1, 1, 2, 3]" yerine bir dizi olabilir; var_dump (json_decode ($ foo)); => dizi (4) {[0] => int (1) [1] => int (1) [2] => int (2) [3] => int (3)}
Misha Nasledov

3

Aşağıdaki sınıfla PHPBench kullanarak aşağıdaki sonuçlar elde edildi:

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

Sonuç: Json'un geçerli olup olmadığını kontrol etmenin en hızlı yolu geri dönmektir json_decode($json, true) !== null).


çok güzel :) sana hayranım
Mehdi

2

Çözümümün performansı veya zarafeti hakkında bir bilgim yok, ama kullandığım şey:

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

Tüm JSON kodlu dizeleri {"ile başlayan bu RegEx ile test etmek için yeterli. RegEx ile hiç akıcı değilim, bu yüzden bunu yapmak için daha iyi bir yol olabilir. Ayrıca: strpos () daha hızlı olabilir.

Sadece tuppence değerinde vermeye çalışıyorum.

PS Sadece RegEx dizesini /^[\[\{]\"/JSON dizi dizelerini bulmak için güncelledi . Şimdi dizenin başında ["ya da {" karakterini arar.


2

Böyle bir şey olmalı:

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

Ünite testi

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

Bunun bir dize olup olmadığını kontrol etmenizi seviyorum. ErrorExceptionDizenin dizi veya nesne olup olmadığını önlemek için ilk çözümle birlikte iyi gider .
sykez

1

Bu cevabı genişletmek Aşağıdakilere ne dersiniz:

<?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
Hata, söz konusu çekte bulunursa zamandan kazanmak için kod çözme yürütülmeden önce alt dize kontrolü yapılmamalı mı? Ben 4 alt dize kontrolleri bir json_decode daha hızlı olacağını düşünürdüm, ama birisi bana bu varsayım ile destek olabilir, ben bu konuda herhangi bir düşünce takdir ediyorum.
Mark

Bu bir ücret argümanı. İşlem süresini bilmiyorum, ancak daha hızlıysa evet.
Sevenearths

1

Merhaba İşte benim kütüphaneden küçük bir snippet, bu ilk durumda sadece veri json olup olmadığını kontrol ediyorum, sonra doğru kod çözülmüşse iade edin, performans için substr kullanımını not edin (henüz başlamayan herhangi bir json dosyası görmedim gönderen {veya [

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

Bu sorunun yanıtı, birçoğu JSON'un bir diziyi veya nesneyi temsil etmesi gerektiği (yanlış) inancına abone olan 34 cevap olmuştur. Bu cevap diğer 3 düzine cevaptan farklı bir şey yapıyor mu?
miken32

1

Benden başka bir öneri :)

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

0

Özel işlev

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

Kılıflar

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

}

kaynaklar

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


0

Başarıyla çözülen verilere ihtiyacınız varsa, PHP 5.2 uyumluluğu için yeni yapılmış işlev:

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

Kullanımı:

$json_or_not = ...;

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

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

Bazı testler:

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
@ hata ayıklama için kullanın (bir hatayı gizleme) ama kesinlikle önerilmez
aswzen

0

En gerekli olasılıklara dokunmak için henrik'in cevabında basit bir değişiklik.

("{} ve []" dahil)

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

Olası bir JSON nesnesini bir PHP nesnesine / dizisine çözmek için belki de en hızlı yol :

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

İşte oluşturduğum performans ve basit bir işlev ( json_decodedaha büyük dizeler için kullanmadan önce temel dize doğrulamasını kullanır ):

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.