161 votes

PHP json_encode : encodage des nombres sous forme de chaînes de caractères

J'ai un problème avec la fonction PHP json_encode. Elle encode les nombres comme des chaînes de caractères, par ex.

array('id' => 3)

devient

"{ ["id": "3", ...)

Lorsque js rencontre ces valeurs, il les interprète comme des chaînes de caractères et les opérations numériques échouent sur elles. Quelqu'un connaît-il un moyen d'empêcher json_encode de l'encodage des nombres en tant que chaînes de caractères ? Merci !

0 votes

Il s'avère que c'est un problème spécifique à une version. Parfois, une extraction d'une base de données MySql maintient les types corrects. Dans les versions plus anciennes, elle peut tout renvoyer sous forme de chaîne. J'ai écrit à ce sujet ce matin. shakyshane.com/blog/output-json-from-php.html

1 votes

J'avais le même problème et j'ai pu le résoudre en utilisant les mutateurs de Laravel dans le modèle. Cela vous permet de modifier les valeurs dans le modèle. laravel.com/docs/eloquent#accessoires-et-mutateurs Je n'ai pas tout compris au début, mais cette question m'a aidé : stackoverflow.com/questions/16985656/

388voto

Rijk Points 4855

Notez que depuis PHP 5.3.3, il y a un drapeau pour la conversion automatique des nombres (le paramètre options a été ajouté en PHP 5.3.0) :

$arr = array( 'row_id' => '1', 'name' => 'George' );
echo json_encode( $arr, JSON_NUMERIC_CHECK ); // {"row_id":1,"name":"George"}

5 votes

Notez que JSON_NUMERIC_CHECK nécessite PHP 5.3.3.

11 votes

Cela fonctionnait parfaitement jusqu'à ce qu'un label numérique soit converti en un nombre entier, ce qui a fait sauter .toLowerCase() dans IE. Attention, cette solution est simple mais trop zélée.

0 votes

@BradKoch Changez la ligne en .toString().toLowerCase() qui fonctionnera avec des nombres ou des chaînes de caractères.

36voto

mouckatron Points 142

De même, je lisais une base de données (PostgreSQL) et tout était une chaîne. Nous bouclons sur chaque ligne et faisons des choses avec elle pour construire notre tableau de résultats final, donc j'ai utilisé

$result_arr[] = array($db_row['name'], (int)$db_row['count']);

dans la boucle pour le forcer à être une valeur entière. Lorsque je fais json_encode($result_arr) maintenant, il le formate correctement comme un nombre. Cela vous permet de contrôler ce qui est et n'est pas un nombre provenant de votre base de données.

EDITAR:

El json_encode() a également la capacité de faire cela à la volée en utilisant la fonction JSON_NUMERIC_CHECK comme second argument. Vous devez cependant faire attention en l'utilisant, comme le montre cet exemple d'utilisateur dans la documentation (copié ci-dessous) : http://uk3.php.net/manual/en/function.json-encode.php#106641

<?php
// International phone number
json_encode(array('phone_number' => '+33123456789'), JSON_NUMERIC_CHECK);
?>

Et ensuite vous obtenez ce JSON :

{"phone_number":33123456789}

0 votes

Oui, il semble que le problème vienne de l'adaptateur DB qui n'interprète pas les types de données, PAS de l'application json_encode C'est la réponse la plus correcte, mais faites attention car JSON_NUMERIC_CHECK convertit également les numéros de téléphone et d'autres chaînes de valeurs numériques, ce qui peut poser des problèmes au niveau des zéros en tête ou des '+'... Je suggère de corriger ce problème dans la fonction de lecture de la BD.

32voto

Pascal MARTIN Points 195780

J'ai fait un test très rapide :

$a = array(
    'id' => 152,
    'another' => 'test',
    'ananother' => 456,
);
$json = json_encode($a);
echo $json;

Cela ressemble à ce que vous décrivez, si je ne me trompe pas ?

Et j'obtiens comme résultat :

{"id":152,"another":"test","ananother":456}

Donc, dans ce cas, les entiers n'ont pas été convertis en chaîne de caractères.

Cependant, cela peut dépendre de la version de PHP que nous utilisons : quelques bugs liés à json_encode ont été corrigés, selon la version de PHP...

Ce test a été effectué avec PHP 5.2.6 ; j'obtiens la même chose avec PHP 5.2.9 et 5.3.0 ; je n'ai pas d'autre version 5.2.x à tester, cependant :-(

Quelle version de PHP utilisez-vous ? Ou bien votre test-case est-il plus complexe que l'exemple que vous avez posté ?

Peut-être un rapport de bug sur http://bugs.php.net/ pourraient être liées ? Par exemple, Bogue n° 40503 : La conversion des entiers de json_encode est incohérente avec PHP. ?

Peut-être Bogue n° 38680 pourrait vous intéresser aussi, d'ailleurs ?

0 votes

Merci Martin. J'utilise la version 5.2.9. Je me demande si les données numériques sont lues à partir de la base de données en tant que chaîne de caractères ? Je suis sûr que les types de champs sont int, mais je ne vois pas d'autre explication. Je vais essayer votre test rapide sur mon système et voir si j'obtiens le même résultat.

14 votes

OK à propos de 5.2.9 ; si vos données proviennent d'une base de données, le problème peut être là : j'ai souvent vu des données provenant d'une base de données avec tout ce qui est casté en chaîne (j'ai vu cela avec PDO et mssql ; mais, si je me souviens bien, cela arrive aussi pour MySQL en PHP < 5.3, quand le nouveau pilote mysqlnd n'existait pas encore) ; ; pour vérifier à quoi ressemblent vos données, vous pouvez utiliser var_dump, qui affiche les types de chaque partie des données.

0 votes

(suite) pense que le type de données pour les valeurs numériques est une chaîne de caractères ? Vous avez une idée ?

9voto

habibillah Points 41

Essayez $arr = array('var1' => 100, 'var2' => 200); $json = json_encode( $arr, JSON_NUMERIC_CHECK);

Mais il ne fonctionne que sur PHP 5.3.3. Regardez le journal des modifications de PHP json_encode. http://php.net/manual/en/function.json-encode.php#refsect1-function.json-encode-changelog

0 votes

Cela a fonctionné pour moi. Installation par défaut de PHP+apache sur debian squeeze 6.0.5 avec des données provenant de postgre db

7voto

oli_arborum Points 169

Je rencontre le même problème (PHP-5.2.11/Windows). J'utilise cette solution de contournement

$json = preg_replace( "/\"(\d+)\"/", '$1', $json );

qui remplace tous les nombres (entiers et non négatifs) entre guillemets par le nombre lui-même (" 42 " devient " 42 ").

Voir aussi ce commentaire dans le manuel PHP .

0 votes

Merci pour le code, mais malheureusement il ne fonctionne pas sur mon json car j'ai un nombre comme nom d'objet, et il semble rendre le json invalide :(

0 votes

@SSHThis, vous devriez peut-être utiliser cette syntaxe pour convertir le tableau en un tableau codé JSON et non en un objet. $json_array = json_encode($some_array, false); Donc l'argument false indique à PHP de ne pas faire la conversion d'objet.

0 votes

Ce n'est pas sûr du tout d'utiliser cette solution de contournement. Vous obtiendrez un json invalide avec de telles structures : json_encode(array(-1=>'que', '0'=>'-1'))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X