J'ai besoin d'une méthode très rapide pour vérifier si une chaîne est au format 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;
}
Les amateurs de performance veulent-ils améliorer cette méthode?
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
Réponse à la question
La fonction json_last_error
renvoie la dernière erreur survenue lors du codage 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 json_last_error
est pris en charge dans PHP> = 5.3.0 uniquement.
Programme complet pour vérifier l'ERREUR exacte
Il est toujours bon de connaître l'erreur exacte pendant la période de développement. Voici le programme complet pour vérifier l'erreur exacte en fonction de la documentation 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_error
n'est pas pris en charge dans PHP 5.2, vous pouvez vérifier si le codage ou le décodage retourne boolean FALSE
. Voici un exemple
// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
// JSON is invalid
}
J'espère que c'est utile. Bon codage!
Utiliser json_decode
pour "sonder" ce n’est peut-être pas le moyen le plus rapide. S'il s'agit d'une structure profondément imbriquée, alors instancier un grand nombre d'objets de tableaux pour les jeter, est un gaspillage de mémoire et de temps.
Il serait donc plus rapide d’utiliser preg_match
et le RFC4627 regex pour également 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));
Pas assez d'un amateur de performance à se soucier de repères ici cependant.
Tout ce que vous avez vraiment besoin de faire, c'est ceci ...
if (is_object(json_decode($MyJSONArray)))
{
... do something ...
}
Cette demande ne nécessite même pas une fonction séparée. Enroulez simplement is_object autour de json_decode et continuez. On dirait que cette solution fait que les gens y mettent beaucoup trop de réflexion.
Cela retournera true si votre chaîne représente un tableau ou objet json:
function isJson($str) {
$json = json_decode($str);
return $json && $str != $json;
}
Il rejette les chaînes JSON contenant uniquement un nombre, une chaîne ou un booléen, bien que ces chaînes soient techniquement valides.
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.
function is_json($str){
return json_decode($str) != null;
}
http://tr.php.net/manual/en/function.json-decode.php La valeur de retour est null si un codage non valide est détecté.
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.
Si vous devez valider votre code 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 la valeur true si c'est un JSON valide.
Vous devez valider votre entrée pour vous assurer que la chaîne que vous transmettez 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;
}
Dans PHP, je pense qu'il est plus important de déterminer si l'objet JSON même has data, car pour utiliser les données, vous devez appeler json_encode()
ou json_decode()
. Je suggère de refuser les objets JSON vides afin d'éviter toute exécution inutile d'encodages et de décodages sur des 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;
}
Méthode simple est de 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';
}
Cela va le faire:
function isJson($string) {
$decoded = json_decode($string);
if ( !is_object($decoded) && !is_array($decoded) ) {
return false;
}
return (json_last_error() == JSON_ERROR_NONE);
}
if ( isJson($someJsonString) ) {
echo "valid JSON";
} else {
echo "not valid JSON";
}
Auparavant, je cherchais simplement une valeur nulle, ce qui était faux en réalité.
$data = "ahad";
$r_data = json_decode($data);
if($r_data){//json_decode will return null, which is the behavior we expect
//success
}
Le code ci-dessus fonctionne bien avec des chaînes. Cependant, dès que je fournis un numéro, il se sépare 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 résoudre 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";
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;
}
Un autre moyen simple
function is_json($str)
{
return is_array(json_decode($str,true));
}
Nous devons vérifier si la chaîne transmise n'est pas numérique car dans ce cas, json_decode ne génère 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;
}
J'ai essayé certaines de ces solutions mais rien ne fonctionnait pour moi. J'essaye 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 solution puisque JSON décode sans le second paramètre donner 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 si c'est un tableau.
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);
}
}
Je ne connais pas les performances ni 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 ...
}
}
Puisque toutes mes chaînes encodées JSON commencent par {", il suffit de tester cela avec un RegEx. Je ne parle pas du tout couramment RegEx, il pourrait donc y avoir un meilleur moyen de le faire. Aussi: strpos () pourrait être plus rapide.
J'essaie juste de donner ma valeur à tuppence.
P.S. Vient de mettre à jour la chaîne RegEx sur /^[\[\{]\"/
afin de rechercher également les chaînes de tableau JSON. Donc, il cherche maintenant soit ["ou {" au début de la chaîne.
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);
?>
Fonction fraîchement créée 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)
Une autre suggestion de moi :)
function isJson(string $string) {
return ($result = json_decode($string, true)) ? $result : $string;
}
Bonjour, voici un petit extrait de ma bibliothèque. Dans cette première condition, je vérifie simplement si les données sont au format json, puis nous les renvoyons si elles sont correctement décodées. Veuillez noter l’utilisation de sous-substrat pour les performances (je n’ai encore vu aucun fichier json ne commençant ni 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
}
}
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));
}
Le moyen le plus rapide de peut-être de décoder 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;
}
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;
}
Cas
$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
Une simple modification de la réponse de henrik pour toucher la plupart des possibilités requises.
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;
}