Il modo più veloce per verificare se una stringa è JSON in PHP?


385

Ho bisogno di un metodo molto, molto veloce per verificare se una stringa è JSON o meno. Sento che questo non è il modo migliore:

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

Qualche appassionato di prestazioni là fuori vuole migliorare questo metodo?


3
Considera di usare solo json_decodeuna volta ... inoltre, controlla i valori di input e return di json_decode.

5
Quindi, qual è la risposta?
Farid Rn,

8
L'interruttore ternario qui è ridondante. La tua dichiarazione è già considerata booleana.
ho lottato con un orso.


Accetta la risposta di Lewis Donovan ... funziona bene
Poonam Bhatt,

Risposte:


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

19
Sembra che tutti stiano amando questa risposta. Qualche spiegazione perché?
Kirk Ouimet,

8
Credo che PHP 5.3> sia necessario per usare la funzione json_last_error
Chris Harrison,

97
Controllo primo carattere di stringa per {, [o primo simbolo di qualsiasi altro letterale può potenzialmente accelerare notevolmente questo quando molti di stringhe in arrivo dovrebbero essere non JSON.
Oleg V. Volkov,

20
$ phone = '021234567'; var_dump (isJson ($ telefono)); ritorna vero no! dovrebbe restituire false.
Vee

23
Attenzione, questa funzione restituirà true anche per qualsiasi numero, indipendentemente dal fatto che sia specificato come stringa o numero reale. 6.5 = true, '300' = true, 9 = trueecc. Quindi questo potrebbe essere un valore JSON valido ma la funzione potrebbe non funzionare come previsto, se si desidera verificare solo le stringhe JSON valide con {}o [];
BadHorsie,

156

Rispondi alla domanda

La funzione json_last_errorrestituisce l'ultimo errore verificatosi durante la codifica e decodifica JSON. Quindi il modo più veloce per controllare il JSON valido è

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

Nota che json_last_errorè supportato solo in PHP> = 5.3.0.

Programma completo per verificare l'esatto ERRORE

È sempre bene conoscere l'errore esatto durante il tempo di sviluppo. Ecco il programma completo per controllare l'errore esatto in base ai documenti 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;
}

Test con INGRESSO JSON valido

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

OUTPUT valido

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

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

Test con JSON non valido

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

OUTPUT non valido

Syntax error, malformed JSON.

Nota aggiuntiva per (PHP> = 5.2 && PHP <5.3.0)

Poiché json_last_errornon è supportato in PHP 5.2, puoi verificare se la codifica o la decodifica restituiscono valori booleani FALSE. Ecco un esempio

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

Spero sia utile. Buona programmazione!


Piccola precisione: se questo json è valido ma un precedente decodificato non è valido, il codice funzionerà correttamente, perché: " Restituisce l'ultimo errore (se presente) verificatosi durante l' ultima codifica / decodifica JSON. "
Bruno

Grazie @Madan, la verifica "json_decode" mi ha risolto che ho eseguito PHP 7.0.
Francis Rodrigues,

Sicuramente json_decode potrebbe restituire false per il falso letterale, quindi un controllo ((strlen($json) === 5) && ($json !== 'false'))dovrebbe essere intrapreso anche per evitare quel limite?
MrMesees,

@Bruno Se l'ultima decodifica funziona senza errori, json_last_errorritorna JSON_ERROR_NONE.
Andrea,

80

Tutto quello che devi fare è questo ...

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

Questa richiesta non richiede nemmeno una funzione separata. Basta avvolgere is_object attorno a json_decode e andare avanti. Sembra che questa soluzione induca le persone a pensarci troppo.


1
@ RomanM.Kos Per essere chiari, se l'array è un array semplice, è necessario utilizzarlo is_arrayin aggiunta is_object, altrimenti is_objectrestituirà false per array semplici codificati come JSON. Quindi @ggutenberg ha ragione in questo caso. Passando l'argomento vero per json_decodeforzare un oggetto a essere restituito come un array. In teoria si potrebbe sempre forzare la decodifica su un array e controllarlo is_array, che dovrebbe funzionare.
userabuser

@userabuser Se json_encode($array)per un semplice array PHP, quindi json_decode($str)riceverò un oggetto, ma non un array. json_decode($str, true)forza la conversione in array. Perché stringhe complicate nel tuo codice? Controlla is_array(json_decode($str, true))e qualche tempo dopo, quando lo leggi capirai che decodificato deve essere solo un array. Molto più difficile da indovinare is_object(json_decode($MyJSONArray))"Oh, sto verificando la decodifica è un array o no?"
Roman M. Koss,

@ RomanM.Kos No, non è corretto, codepad.viper-7.com/OFrtsq - come ho detto, puoi sempre forzare json_decodea restituire un array per salvarti controllando l'oggetto e l'array, ma se non lo fai E tu json_decodecosa era un array semplice per cominciare, riceverai un array in cambio della decodifica, non un oggetto. È necessario utilizzare JSON_FORCE_OBJECTse si desidera forzare sempre un oggetto sulla codifica IF passando un array semplice.
userabuser,

11
Downvote per dire: This request does not require a separate function even. A rigor di termini, nessuna soluzione richiede una funzione separata. Il punto di una funzione non è far apparire più righe di codice come una riga di codice. Il punto della funzione è rendere lo standard del processo di controllo JSON standard ovunque nell'applicazione, in modo che programmatori diversi (o lo stesso programmatore nel tempo) non utilizzino procedure di controllo diverse nelle diverse fasi del flusso del programma.
cartbeforehorse

71

Usando json_decodeper "sondare" potrebbe non essere effettivamente il modo più veloce. Se è una struttura profondamente annidata, creare un'istanza di molti oggetti di array per buttarli via è una perdita di memoria e di tempo.

Quindi potrebbe essere più veloce da usare preg_matche il regex RFC4627 per garantire anche la validità :

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

Lo stesso in PHP:

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

Tuttavia, non è abbastanza un appassionato di prestazioni per preoccuparsi dei benchmark qui.


11
Regex completo ricorsivo per verificare JSON qui: stackoverflow.com/questions/2583472/regex-to-validate-json/… - Ma risulta che i PHP json_decodesono sempre più veloci di un regex PCRE. (Anche se non è molto ottimizzato, non sono stati trovati test sintetici e potrebbe comportarsi diversamente in Perl ..)
mario

3
@vee Sì, grazie per la nota. Ma teniamolo qui [in modo errato], quindi nessuno lo utilizza effettivamente in produzione.
Mario,

1
@cartbeforehorse Va bene, grazie. Ho quindi risolto il problema del escape escape per i PHP con il doppio contesto delle stringhe.
Mario,

1
@cartbeforehorse Non lo fa. Principalmente decorazione. È solo la barra rovesciata letterale che richiede davvero doppiamente fuga. Perché \r \n \tha senso, quindi PHP non li interpola, ma lascia che PCRE li interpreti (era richiesto solo per la /xmodalità). Le altre occorrenze non ne hanno strettamente bisogno; eppure "la barra rovesciata si sfugge da sola" in tutti i contesti PHP di stringhe. Quindi uno potrebbe considerarlo più esatto.
mario,

4
@mario Okay, capisco. Quindi, in sostanza, il PHP sfugge alle barre rovesciate prima che il motore reg-exp riesca a vederlo. Per quanto riguarda il motore reg-exp, ci sono metà del numero di barre rovesciate nella stringa rispetto a ciò che noi umani vediamo. "Come reg-exp non era già abbastanza complicato"
cartbeforehorse

39

Questo restituirà vero se la tua stringa rappresenta un array o un oggetto json :

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

Rifiuta le stringhe json che contengono solo un numero, una stringa o un valore booleano, sebbene quelle stringhe siano json tecnicamente valide.

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)

È il modo più breve con cui posso inventarmi.


Invece di var_dump, potresti metterlo in un caso di test PHPUnit. Altrimenti sono sorpreso e felice di sapere che è vero.
MrMesees,

3
Perché tutti gli altri hanno risposte così lunghe quando funziona alla grande? Grazie.
toddmo,

1
Semplicemente adorabile! Non ho cercato il "modo più veloce" o le prestazioni sagge, ma questo sicuramente copre tutti i casi che avrei mai verificato. Questo è un classico esempio del famigerato proverbio "Non usare la mazza per rompere un dado" . Dal punto di vista del programmatore, è sempre meglio mantenere il codice semplice, breve e di facile comprensione, prestazioni e semplicità sono un altro dibattito fuori portata per questo thread.
Venerdì

Questo è un bel po 'di logica, ma nota anche che restituisce false per array vuoti. Ad esempio: var_dump(isJson('[]')); // bool(false). Secondo la documentazione sui booleani, ciò è dovuto al fatto che PHP valuta false le matrici con zero elementi. Ecco un piccolo emendamento per adeguare la dichiarazione di reso; esegue un confronto identico sull'output decodificato che gestisce questo caso:return $json !== false && $str != $json;
j13k

@ j13k Il confronto identico viene valutato isJson('hello')su true, che non è json valido. Il confronto libero è scelto apposta qui. Non ho una soluzione rapida per la situazione vuota di array / oggetti, tranne un bruttoreturn $json == '[]' || ...
Cyril

21

Il modo più semplice e veloce che utilizzo è il seguente;

$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

È perché json_decode () restituisce NULL se la stringa immessa non è json o json non valido.


Semplice funzione per convalidare JSON

Se devi convalidare JSON in più posizioni, puoi sempre utilizzare la seguente funzione.

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

Nella funzione precedente, otterrai true in cambio se si tratta di un JSON valido.


3
json_decode('null') == NULLed nullè un valore JSON valido.
zzzzBov

Ho verificato se 'null' è valido per json su json.parser.online ma sembra che non sia valido per json. E json_decode () è la funzione principale di php per convalidare json, quindi dubito di ottenere dei risultati falsi nel nostro output.
Mohammad Mursaleen,

Invece di fidarti di un sito Web non verificato, considera di consultare la specifica, che non è d'accordo (pag. 2) . In alternativa, prova JSON.parse('null')nella tua console di sviluppo.
zzzzBov,

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

http://tr.php.net/manual/en/function.json-decode.php il valore restituito è nullo quando viene rilevata una codifica non valida.


4
Restituirà inoltre in modo errato null per "null" (che non è JSON valido, ma potrebbe essere del tutto "valido" in json_decode altrimenti). Vai a capire.

Penso che questo potrebbe essere: json_decode($str)!=null;o altrimenti dovrebbe essere chiamata la funzione is_not_json.
Yoshi,

Quella funzione sarebbe meglio rinominata "è qualcosa di diverso da JSON"!
lunedì

2
@ user166390, json_decode('null')è JSON valido in base alle specifiche e deve restituire il valore di null.
zzzzBov

Si noti inoltre che con questo metodo is_json('false')e is_json('[]')verrà restituito falsepoiché il tipo non è selezionato. Penso che questo metodo dovrebbe piuttosto tornare $str === null || json_decode($str) !== null.
Antoine Pinsard,

11

È necessario convalidare l'input per assicurarsi che la stringa che si passa non sia vuota e sia, di fatto, una stringa. Una stringa vuota non è JSON valida.

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

Penso che in PHP sia più importante determinare se l'oggetto JSON ha anche dei dati, perché per usare i dati dovrai chiamare json_encode()o json_decode(). Suggerisco di negare oggetti JSON vuoti in modo da non eseguire inutilmente codifiche e decodifiche su dati vuoti.

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 per aver effettivamente pensato al problema in un contesto reale.
cartbeforehorse

Ma '0'non è valido JSON ... perché dovrei essere cauto? @Kzqai
upful

11

Questo lo farà:

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

Come mostrato in altre risposte, json_last_error()restituisce qualsiasi errore dal nostro ultimo json_decode (). Tuttavia, ci sono alcuni casi di utilizzo dei bordi in cui questa funzione da sola non è sufficientemente completa. Ad esempio, se si utilizza json_decode()un numero intero (ad esempio:) 123o una stringa di numeri senza spazi o altri caratteri (ad esempio:) "123", la json_last_error()funzione non rileverà un errore.

Per combattere questo, ho aggiunto un ulteriore passaggio che garantisce che il risultato del nostro json_decode()sia un oggetto o un array. In caso contrario, torniamo false.

Per vederlo in azione, controlla questi due esempi:


"hello"è un JSON valido e non è un oggetto né un array, json_last_error()è sufficiente
JoniJnm,

1
json_last_error()restituisce il codice di errore 4quando si json_decode()la stringa "hello". Esempio qui: 3v4l.org/lSsEo
Lewis Donovan,

Il tuo codice è errato, hellonon è un JSON valido, ma "hello"è 3v4l.org/OEJrQ
JoniJnm

9

Il metodo semplice è controllare il risultato JSON.

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

6

in 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

Prima stavo solo controllando un valore nullo, che in realtà era sbagliato.

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

Il pezzo di codice sopra funziona bene con le stringhe. Tuttavia, non appena fornisco il numero, si rompe, ad esempio.

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

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

Per risolvere quello che ho fatto è stato molto semplice.

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

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

Bella soluzione. Gestisce molto bene la questione della digitazione!
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

Un altro modo semplice

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

1
Questo non è corretto Qualsiasi tipo di PHP può essere codificato in JSON come oggetti, stringhe, ecc. E la funzione json_decode dovrebbe restituirli. Questo è vero solo se si decodificano sempre array e non si hanno altri tipi di variabili.
Chaoix,

L'utilizzo di @Chaoix json_decode($str,true)consente di convertire gli oggetti in array in modo da passare il controllo is_array. Correggi su stringhe, numeri interi, ecc. Però.
Paul Phillips,

Vedo il significato del secondo parametro su json_encode. Penso ancora che la soluzione di @Ahad Ali sia molto migliore in termini di digitazione e di fare un json_decode solo una volta nei tuoi algoritmi.
Chaoix,

4

Dobbiamo verificare se la stringa passata non è numerica perché in questo caso json_decode non genera alcun errore.

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

    return $result;
}

4

Ho trovato questa domanda dopo essermi imbattuto in qualcosa di simile nel mio lavoro, ieri. La mia soluzione alla fine era un ibrido di alcuni degli approcci sopra:

function is_JSON($string) {

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

  return $String_Is_JSON;
}

3

Ho provato alcune di quelle soluzioni, ma nulla funzionava per me. Provo questa semplice cosa:

$isJson = json_decode($myJSON);

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

Penso che sia un'ottima soluzione poiché la decodifica JSON senza il secondo parametro dà un oggetto.

EDIT: se sai quale sarà l'input, puoi adattare questo codice alle tue esigenze. Nel mio caso so di avere un Json che inizia con "{", quindi non ho bisogno di verificare se si tratta di un array.


Il tuo JSON potrebbe potenzialmente essere solo un array, nel qual caso sarebbe un array anziché anziché stdClass $ foo = "[1, 1, 2, 3]"; var_dump (json_decode ($ pippo)); => array (4) {[0] => int (1) [1] => int (1) [2] => int (2) [3] => int (3)}
Misha Nasledov

3

Utilizzando PHPBench con la seguente classe, sono stati raggiunti i seguenti risultati:

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

Conclusione: il modo più rapido per verificare se json è valido è tornare json_decode($json, true) !== null).


molto bello :) ti ammiro
Mahdi

2

Non conosco le prestazioni o l'eleganza della mia soluzione, ma è quello che sto usando:

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

Poiché tutte le mie stringhe con codifica JSON iniziano con {", è sufficiente testarlo con un RegEx. Non sono affatto fluente con RegEx, quindi potrebbe esserci un modo migliore per farlo. Inoltre: strpos () potrebbe essere più veloce.

Sto solo cercando di dare il mio valore.

PS Ho appena aggiornato la stringa RegEx /^[\[\{]\"/per trovare anche le stringhe di array JSON. Quindi ora cerca ["o {" all'inizio della stringa.


2

Dovrebbe essere qualcosa del genere:

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

Mi piace che stai controllando se è una stringa. Va bene in combinazione con la prima soluzione per evitare ErrorExceptionse la stringa è un array o un oggetto.
Sykez,

1

Espandendo su questa risposta Che ne dici di quanto segue:

<?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
Il controllo di sottostringa non dovrebbe essere eseguito prima di eseguire la decodifica per risparmiare tempo se l'errore viene rilevato in quel controllo? Immagino che 4 controlli di sottostringa sarebbero più veloci di un json_decode, ma se qualcuno potesse supportarmi con questa ipotesi apprezzerei ogni pensiero su questo.
Segna il

Questo è un argomento tariffario. Non conosco i tempi di elaborazione, ma se è più veloce allora sì.
Sevenearths,

1

Ciao, ecco un piccolo frammento della mia libreria, in questa prima condizione sto solo verificando se i dati sono json quindi li restituiscono se correttamente decodificati, si prega di notare l'uso del substr per le prestazioni (non ho ancora visto alcun file json che non inizia né di {o [

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

Sono state inviate 34 risposte a questa domanda, molte delle quali sottoscrivono anche la convinzione (errata) che JSON debba rappresentare un array o un oggetto. Questa risposta sta facendo qualcosa di diverso dalle altre 3 dozzine di risposte?
miken32,

1

Un altro suggerimento da parte mia :)

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

0

La funzione personalizzata

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

casi

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

}

risorse

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


0

Funzione appena creata per la compatibilità con PHP 5.2, se hai bisogno dei dati decodificati in caso di successo:

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

Uso:

$json_or_not = ...;

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

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

Alcuni test:

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
@ Uso per il debug (che nasconde un errore), ma la sua non è assolutamente consigliato
aswzen

0

Una semplice modifica alla risposta di Henrik per toccare le possibilità più richieste.

(compresi "{} e []")

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

Il modo più veloce per forse decodificare un possibile oggetto JSON in un oggetto / array PHP:

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

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

0

Ecco una funzione performante e semplice che ho creato (che utilizza la convalida della stringa di base prima di utilizzarla json_decodeper stringhe più grandi):

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.