Le moyen le plus rapide de vérifier si une chaîne est JSON en PHP?

385

J'ai besoin d'une méthode vraiment, vraiment rapide pour vérifier si une chaîne est JSON ou non. J'ai l'impression que ce n'est pas la meilleure façon:

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

Des amateurs de performances veulent améliorer cette méthode?

Kirk Ouimet
la source
3
N'utilisez qu'une seule json_decodefois ... vérifiez également les valeurs d'entrée et de retour de json_decode.
5
Alors, laquelle est la réponse?
Farid Rn
8
Le commutateur ternaire ici est redondant. Votre déclaration est déjà évaluée comme un booléen.
J'ai lutté un ours une fois.
Acceptez la réponse de Lewis Donovan ... ça fonctionne bien
Poonam Bhatt

Réponses:

574
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}
Henrik P. Hessel
la source
19
On dirait que tout le monde aime cette réponse. Une explication pourquoi?
Kirk Ouimet
8
Je crois que PHP 5.3> est nécessaire pour utiliser la fonction json_last_error
Chris Harrison
97
Vérification premier caractère de chaîne pour {, [ou premier symbole de tout autre littéral peut accélérer considérablement potentiellement celui - ci lorsque la plupart des chaînes entrantes devraient être non JSON.
Oleg V. Volkov,
20
$ phone = '021234567'; var_dump (isJson ($ phone)); retour vrai non! il devrait retourner faux.
vee
23
Attention, cette fonction renverra également vrai pour n'importe quel nombre, que vous le spécifiiez sous forme de chaîne ou de vrai nombre. 6.5 = true, '300' = true, 9 = trueetc. Il peut donc s'agir d'une valeur JSON valide mais la fonction peut ne pas se comporter comme prévu, si vous souhaitez rechercher uniquement des chaînes JSON valides avec {}ou [];
BadHorsie
156

Réponse à la question

La fonction json_last_errorrenvoie la dernière erreur survenue lors de l'encodage et du décodage JSON. Donc, le moyen le plus rapide de vérifier le JSON valide est

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

Notez que cela json_last_errorn'est pris en charge qu'en PHP> = 5.3.0.

Programme complet pour vérifier l'erreur exacte

Il est toujours bon de connaître l'erreur exacte pendant le temps de développement. Voici un programme complet pour vérifier l'erreur exacte sur la base des documents 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 avec une entrée JSON valide

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

SORTIE valide

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

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

Test avec JSON invalide

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

SORTIE invalide

Syntax error, malformed JSON.

Note supplémentaire pour (PHP> = 5.2 && PHP <5.3.0)

Étant donné que json_last_errorn'est pas pris en charge en PHP 5.2, vous pouvez vérifier si l'encodage ou le décodage retourne booléen FALSE. Voici un exemple

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

J'espère que cela vous sera utile. Codage heureux!

Madan Sapkota
la source
Peu de précision: si ce json est valide mais qu'un précédent décodé n'est pas valide, votre code va fonctionner correctement, car: " Retourne la dernière erreur (le cas échéant) survenue lors du dernier encodage / décodage JSON. "
Bruno
Merci @Madan, la vérification "json_decode" m'a résolu que j'utilisais PHP 7.0.
Francis Rodrigues du
Sûrement json_decode pourrait simplement retourner false pour le faux littéral, donc une vérification ((strlen($json) === 5) && ($json !== 'false'))devrait également être entreprise pour éviter ce bord?
MrMesees
@Bruno Si le dernier décodage fonctionne sans erreur, il json_last_errorrevient JSON_ERROR_NONE.
Andrea
80

Tout ce que vous devez vraiment faire, c'est ceci ...

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

Cette demande ne nécessite même pas de fonction distincte. Enroulez simplement is_object autour de json_decode et continuez. Il semble que cette solution incite les gens à y réfléchir beaucoup trop.

user1653711
la source
1
@ RomanM.Kos Juste pour être clair, si le tableau est un tableau simple, alors vous devez l'utiliser is_arrayen plus de is_object, sinon is_object, retournera false pour les tableaux simples encodés en JSON. Donc @ggutenberg a raison dans ce cas. Passer l'argument true pour json_decodeforcer un objet à être renvoyé sous forme de tableau. Vous pourriez en théorie toujours forcer le décodage vers un tableau et juste vérifier is_array, cela devrait fonctionner.
userabuser
@userabuser Si je json_encode($array)pour un tableau PHP simple, puis- json_decode($str)je recevoir un objet, mais pas un tableau. json_decode($str, true)force à convertir en tableau. Pourquoi une chaîne compliquée dans votre code? Vérifiez is_array(json_decode($str, true))et quelque temps plus tard, lorsque vous le lirez, vous comprendrez que le décodage ne doit être qu'un tableau. Beaucoup plus difficile à deviner is_object(json_decode($MyJSONArray))"Oh, ici je vérifie que le décodage est un tableau ou non?"
Roman M. Koss
@ RomanM.Kos Non, ce n'est pas correct, codepad.viper-7.com/OFrtsq - comme je l'ai dit, vous pouvez toujours forcer json_decodeà renvoyer un tableau pour vous éviter de vérifier l'objet et le tableau, mais si vous ne le faites pas ET vous json_decodequoi était un simple tableau pour commencer, vous recevrez un tableau en retour lors du décodage, pas un objet. Vous devez utiliser JSON_FORCE_OBJECTsi vous souhaitez toujours forcer un objet à encoder IF en passant un simple tableau.
userabuser
11
Downvote pour dire: This request does not require a separate function even. À strictement parler, aucune solution ne nécessite une fonction distincte. Le but d'une fonction n'est pas de faire ressembler plusieurs lignes de code à une seule ligne de code. Le but de la fonction est de rendre le processus de vérification JSON standard partout dans votre application, afin que différents programmeurs (ou le même programmeur au fil du temps) n'utilisent pas de procédures de vérification différentes à différentes étapes du flux du programme.
cartbeforehorse
71

Utiliser json_decodepour "sonder" ce n'est peut-être pas le moyen le plus rapide. S'il s'agit d'une structure profondément imbriquée, instancier de nombreux objets de tableaux pour les jeter est une perte de mémoire et de temps.

Il pourrait donc être plus rapide à utiliser preg_matchet RFC4627 regex aussi assurer la validité :

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

La même chose en PHP:

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

Cependant, pas assez d'un passionné de performance pour se soucier des repères.

mario
la source
11
Terminez l'expression rationnelle récursive pour vérifier JSON ici: stackoverflow.com/questions/2583472/regex-to-validate-json/… - Mais il s'avère que PHP json_decodeest toujours plus rapide qu'une expression régulière PCRE. (Bien qu'il ne soit pas très optimisé, aucun test synthétique n'a été trouvé et pourrait se comporter différemment en Perl ..)
mario
3
@vee Oui, merci pour la note. Mais gardons-le ici [incorrectement], donc personne ne l'utilise réellement en production.
mario
1
@cartbeforehorse D'accord, merci. J'ai alors corrigé le sain échappement pour le contexte de chaîne entre guillemets doubles PHP.
mario
1
@cartbeforehorse Ce n'est pas le cas. Surtout la décoration. C'est juste la barre oblique inverse littérale qui nécessite en effet une double évasion. Car \r \n \tcela n'a de sens que si PHP ne les interpole pas, mais laisse PCRE les interpréter (seul était requis pour le /xmode). Les autres événements n'en ont pas strictement besoin; pourtant, "la barre oblique inverse s'échappe" dans tous les contextes PHP de chaîne. On pourrait donc le considérer comme plus exact.
mario
4
@mario D'accord, je vois. Donc, fondamentalement, le PHP échappe aux barres obliques inverses avant que le moteur reg-exp ne puisse le voir. En ce qui concerne le moteur reg-exp, il y a la moitié du nombre de barres obliques inverses dans la chaîne comme ce que nous, les humains, voyons. "Comme reg-exp n'était pas déjà assez compliqué"
cartbeforehorse
39

Cela retournera vrai si votre chaîne représente un tableau ou un objet json :

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

Il rejette les chaînes json qui ne contiennent qu'un nombre, une chaîne ou un booléen, bien que ces chaînes soient techniquement valides 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)

C'est le moyen le plus court que je puisse trouver.

Cyril
la source
Plutôt que var_dump, vous pourriez mettre ceci dans un cas de test PHPUnit. Sinon, je suis à la fois surpris et heureux d'apprendre que c'est vrai.
MrMesees
3
Pourquoi tout le monde a-t-il des réponses si longues si cela fonctionne bien? Merci.
toddmo
1
Tout simplement charmant! Je n'ai pas vérifié le "moyen le plus rapide" ou les performances, mais celui-ci couvre tous les cas que je vérifierais. Ceci est un exemple classique du fameux proverbe "N'utilisez pas de marteau pour casser une noix" . Du point de vue du programmeur, il est toujours préférable de garder le code simple, court et facile à comprendre, performance vs simplicité est un autre débat hors de portée de ce fil.
Fr0zenFyr
C'est un peu logique, mais notez également qu'il renvoie false pour les tableaux vides. Par exemple: var_dump(isJson('[]')); // bool(false). Selon la documentation sur les booléens, c'est parce que PHP évalue les tableaux avec zéro élément comme faux. Voici une modification mineure pour ajuster la déclaration de retour; il effectue une comparaison identique sur la sortie décodée qui gère ce cas:return $json !== false && $str != $json;
j13k
@ j13k La comparaison identique donne la valeur isJson('hello')true, ce qui n'est pas un json valide. La comparaison lâche est choisie exprès ici. Je n'ai pas de solution rapide pour la situation tableau / objet vide, sauf un laidreturn $json == '[]' || ...
Cyril
21

Le moyen le plus simple et le plus rapide que j'utilise est le suivant;

$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

C'est parce que json_decode () renvoie NULL si la chaîne entrée n'est pas json ou json invalide.


Fonction simple pour valider JSON

Si vous devez valider votre JSON à plusieurs endroits, vous pouvez toujours utiliser la fonction suivante.

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

Dans la fonction ci-dessus, vous obtiendrez true en retour s'il s'agit d'un JSON valide.

Mohammad Mursaleen
la source
3
json_decode('null') == NULLet nullest une valeur JSON valide.
zzzzBov
J'ai testé si 'null' est un json valide sur json.parser.online mais il semble que ce ne soit pas un json valide. Et json_decode () est la fonction principale de php pour valider json, donc je doute d'obtenir un résultat faux dans notre sortie.
Mohammad Mursaleen
Plutôt que de faire confiance à un site Web non vérifié, pensez à consulter la spécification, qui n'est pas d'accord (p. 2) . Vous pouvez également essayer JSON.parse('null')dans votre console de développement.
zzzzBov
19
function is_json($str){ 
    return json_decode($str) != null;
}

http://tr.php.net/manual/en/function.json-decode.php la valeur de retour est nulle lorsqu'un encodage non valide a été détecté.

AhmetB - Google
la source
4
Il renverra également de manière incorrecte null pour "null" (qui n'est pas un JSON valide, mais peut être entièrement "valide" pour json_decode sinon). Allez comprendre.
Je pense que cela devrait être: json_decode($str)!=null;sinon la fonction devrait être appelée is_not_json.
Yoshi
Cette fonction serait mieux renommée "est autre chose que JSON"!
lonesomeday
2
@ user166390, json_decode('null')est un JSON valide selon la spécification et doit renvoyer la valeur de null.
zzzzBov
Veuillez également noter qu'avec cette méthode is_json('false')et que le type de is_json('[]')retour falsene sera pas vérifié. Je pense que cette méthode devrait plutôt revenir $str === null || json_decode($str) !== null.
Antoine Pinsard
11

Vous devez valider votre entrée pour vous assurer que la chaîne que vous passez n'est pas vide et est en fait une chaîne. Une chaîne vide n'est pas un JSON valide.

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

Je pense qu'en PHP, il est plus important de déterminer si l'objet JSON a même des données, car pour utiliser les données, vous devrez appeler json_encode()ou json_decode(). Je suggère de refuser les objets JSON vides afin de ne pas exécuter inutilement les encodages et décodages sur les données vides.

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;
}
affreux
la source
+1 pour avoir réellement réfléchi au problème dans un contexte réel.
cartbeforehorse
Mais '0'n'est pas valide json ... pourquoi devrais-je me méfier? @Kzqai
upful
11

Cela le fera:

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

Comme indiqué dans d'autres réponses, json_last_error()retourne toute erreur de notre dernier json_decode (). Cependant, il existe certains cas d'utilisation de pointe où cette fonction seule n'est pas suffisamment complète. Par exemple, si vous êtes json_decode()un entier (par exemple:) 123, ou une chaîne de nombres sans espaces ou autres caractères (par exemple:) "123", la json_last_error()fonction ne détectera pas d'erreur.

Pour lutter contre cela, j'ai ajouté une étape supplémentaire qui garantit que le résultat de notre json_decode()soit un objet ou un tableau. Si ce n'est pas le cas, nous revenons false.

Pour voir cela en action, vérifiez ces deux exemples:

Lewis Donovan
la source
"hello"est un JSON valide, et ce n'est pas un objet ni un tableau, json_last_error()
ça
1
json_last_error()renvoie un code d'erreur 4lorsque vous json_decode()la chaîne "hello". Exemple ici: 3v4l.org/lSsEo
Lewis Donovan
Votre code est incorrect, hellon'est pas un JSON valide, mais "hello"est 3v4l.org/OEJrQ
JoniJnm
9

La méthode la plus simple consiste à vérifier le résultat json.

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

dans 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
la source
5

Plus tôt, je vérifiais simplement une valeur nulle, ce qui était faux en fait.

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

Le morceau de code ci-dessus fonctionne correctement avec les chaînes. Cependant, dès que je fournis un numéro, il se casse, par exemple.

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

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

Pour y remédier, ce que j'ai fait était très simple.

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

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";
Ahad Ali
la source
Belle solution. Gère très bien le problème de frappe!
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
la source
4

Un autre moyen simple

function is_json($str)
{
    return is_array(json_decode($str,true));
}
h0mayun
la source
1
Ce n'est pas correct. Tout type PHP peut être encodé en JSON tel que des objets, des chaînes, etc. et la fonction json_decode devrait les renvoyer. Cela n'est vrai que si vous décodez toujours des tableaux et aucun autre type de variable.
Chaoix
@Chaoix using lui json_decode($str,true)permet de convertir des objets en tableaux afin qu'il passe la vérification is_array. Vous corrigez cependant les chaînes, les entiers, etc.
Paul Phillips
Je vois ce que vous voulez dire sur le deuxième paramètre sur json_encode. Je pense toujours que la solution de @Ahad Ali est bien meilleure en termes de frappe et de ne faire un json_decode qu'une seule fois dans vos algorithmes.
Chaoix
4

Nous devons vérifier si la chaîne passée n'est pas numérique car dans ce cas json_decode ne déclenche aucune erreur.

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
la source
4

J'ai trouvé cette question après avoir rencontré quelque chose de similaire dans mon travail, hier. Ma solution à la fin était un hybride de certaines des approches ci-dessus:

function is_JSON($string) {

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

  return $String_Is_JSON;
}
Rounin
la source
3

J'ai essayé certaines de ces solutions mais rien ne fonctionnait pour moi. J'essaie cette chose simple:

$isJson = json_decode($myJSON);

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

Je pense que c'est une bonne solutiuon puisque le décodage JSON sans le second paramètre donne un objet.

EDIT: Si vous savez quelle sera l'entrée, vous pouvez adapter ce code à vos besoins. Dans mon cas, je sais que j'ai un Json qui commence par "{", donc je n'ai pas besoin de vérifier s'il s'agit d'un tableau.

Greco Jonathan
la source
Votre JSON pourrait potentiellement être simplement un tableau, auquel cas ce serait un tableau plutôt que stdClass $ foo = "[1, 1, 2, 3]"; var_dump (json_decode ($ foo)); => tableau (4) {[0] => int (1) [1] => int (1) [2] => int (2) [3] => int (3)}
Misha Nasledov
3

En utilisant PHPBench avec la classe suivante, les résultats ci-dessous ont été obtenus:

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

Conclusion: le moyen le plus rapide de vérifier si json est valide est de revenir json_decode($json, true) !== null).

Matthew Anderson
la source
très sympa :) je t'admire
Mahdi
2

Je ne connais pas les performances ou l'élégance de ma solution, mais c'est ce que j'utilise:

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

Étant donné que toutes mes chaînes codées JSON commencent par {", il suffit de tester cela avec un RegEx. Je ne suis pas du tout à l'aise avec RegEx, donc il pourrait y avoir une meilleure façon de le faire. Aussi: strpos () pourrait être plus rapide.

J'essaye juste de donner ma valeur de tuppence.

PS Nous venons de mettre à jour la chaîne RegEx /^[\[\{]\"/pour trouver également les chaînes de tableau JSON. Il recherche donc maintenant ["ou {" au début de la chaîne.

maxpower9000
la source
2

Devrait être quelque chose comme ça:

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

Test de l'unité

public function testIsJson()
{
    $non_json_values = [
        "12",
        0,
        1,
        12,
        -1,
        '',
        null,
        0.1,
        '.',
        "''",
        true,
        false,
        [],
        '""',
        '[]',
        '   {',
        '   [',
    ];

   $json_values = [
        '{}',
        '{"foo": "bar"}',
        '[{}]',
        '  {}',
        ' {}  '
    ];

   foreach ($non_json_values as $non_json_value) {
        $is_json = isJson($non_json_value);
        $this->assertFalse($is_json);
    }

    foreach ($json_values as $json_value) {
        $is_json = isJson($json_value);
        $this->assertTrue($is_json);
    }
}
Tinh Dang
la source
J'aime que tu vérifies si c'est une chaîne. Va bien en combinaison avec la première solution pour éviter ErrorExceptionsi la chaîne est un tableau ou un objet.
sykez
1

Développer cette réponse Que diriez-vous de ce qui suit:

<?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
la source
1
La vérification de la sous-chaîne ne doit-elle pas être effectuée avant d'exécuter le décodage pour gagner du temps si l'erreur est trouvée dans cette vérification? J'imagine que 4 vérifications de sous-chaîne seraient plus rapides qu'un json_decode, mais si quelqu'un pouvait me soutenir avec cette hypothèse, j'apprécierais toute réflexion à ce sujet.
Mark
C'est un argument tarifaire. Je ne connais pas le temps de traitement impliqué, mais si c'est plus rapide, alors oui.
Sevenearths
1

Salut, voici un petit extrait de ma bibliothèque, dans cette première condition, je vérifie simplement si les données sont json puis les retourne si elles sont correctement décodées, veuillez noter l'utilisation de substr pour les performances (je n'ai encore vu aucun fichier json ne commençant pas non plus) par {ou [

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

Il y a eu 34 réponses postées à cette question, dont beaucoup souscrivent également à la croyance (erronée) que JSON doit représenter un tableau ou un objet. Cette réponse fait-elle quelque chose de différent des 3 autres douzaines de réponses?
miken32

1

Une autre suggestion de moi :)

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

0

La fonction personnalisée

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

Étuis

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

}

Ressources

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


0

Fonction fraîchement conçue pour la compatibilité PHP 5.2, si vous avez besoin des données décodées en cas de succès:

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

Usage:

$json_or_not = ...;

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

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

Quelques tests:

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
@ utiliser pour le débogage (cacher une erreur) mais ce n'est absolument pas recommandé
aswzen

0

Une simple modification de la réponse de henrik pour toucher la plupart des possibilités requises.

(y compris "{} et []")

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;

}

la source
0

Le moyen le plus rapide de décoder peut-être un objet JSON possible en un objet / tableau 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;
}
Philipp
la source
0

Voici une fonction performante et simple que j'ai créée (qui utilise la validation de chaîne de base avant d'utiliser json_decodepour des chaînes plus grandes):

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

la source