Introduction

JSON est un format d'encodage de données grandement influencé par Javascript mais qui a des limitations bien à lui. On peut souvent utiliser du JSON directement en Javascript mais pas le contraire. On l'utilise dans plusieurs cas comme les fichiers de configurations, les tableaux de données ou la sérialisation. Il peut donc remplacer dans certains cas les configurations écrites dans des fichiers .ini, .xml et on voit aussi YAML c'est temps-ci. On peut l'utiliser pour des tableaux de données anciennement échangés en CSV. On peut aussi l'utiliser comme plateforme de "marshalling" ou sérialisation des données et des requêtes (remplacement de SOAP, CORBA, ...). Une des forces de JSON est la disponibilité de nombreuses bibliothèques dans la majorité des langages de programmation.

PHP possède deux méthodes principales pour le format JSON, soit json_encode() pour l'encodage de données et json_decode() pour la lecture.

Encodage : de PHP vers JSON

$jsonString = json_encode($phpVariable);

JSON permet d'encoder les types de données de PHP selon les limitations de JSON. Voici quelques exemples:

PHP                 Chaîne JSON (en PHP)  Format JSON
false, true         'false', 'true'       false, true
1                   '1'                   1
3.14                '3.14'                3.14
null                'null'                null
'abc\n'             '"abc\\n"'            "abc\\n"
"abc\n"             '"abc\n"'             "abc\n"

// tableau et tableau associatif
[]                  '[]'                  []
[1, 2, 3]           '[1,2,3]'             [1,2,3]
array(1, 2, 3)      '[1,2,3]'             [1,2,3]
array('bla'=>test') '{"bla":"test"}'      {"bla":"test"}
array(1, 'k'=>'v')  '{"0":1,"k":"v"}'     {"0":1,"k":"v"}

// objet
class A {
  public $b = 't';
  public $c = 1;
  protected $c = 'protégé'
  private $d = 'privé';
  const E = 2.718281828459;
}
$a = new A();       '{"b":"t","c":1}'     {"b":"t","c":1}

Pour les tableaux (array), ils seront encodés en tableau seulement si toutes les clés sont numériques et en objet s'il existe une clé non-numérique. Les tableaux vides sont encodés en tableau.

Pour les objets, seulement les attributs publiques sont encodés. Les méthodes, constantes, les propriétés privées et les propriétés protégées ne sont pas encodées.

Décodage : de JSON vers PHP

$variablePHP = json_decode($jsonString, $assoc = false);

json_decode permet le décodage d'une chaîne qui contient le format JSON dans des types de données PHP simples (objet, tableau, booléen, entier, nombre à virgule, chaîne de caractère, null).

Par défaut, les objets seront encodés dans un objet PHP (stdClass) et non un tableau associatif (array). On peut modifier se comportement avec le deuxième argument de json_decode $assoc et le placer à true. Exemple:

Code:
$o = json_decode('{"k":1}');
var_dump($o);
echo $o->k;

Résultat:
object(stdClass)#1 (1) {
  ["k"]=>
  int(1)
}
1

Code:
$a = json_decode('{"k":1}', true);
var_dump($a);
echo $a['k'];

Résultat:
array(1) {
  ["k"]=>
  int(1)
}
1

Piège pour débutant

Bien que le format JSON soit simple à lire pour un humain ou simple à écrire, il faut éviter le piège d'écrire du JSON manuellement, sans utiliser la fonction json_encode. Si on intègre des chaînes contenant du JSON dans une structure à encoder, il faut mieux décoder les chaînes et les réencoder par la suite. (cas vu sur IRC en janvier 2018).

Il faut donc éviter:

$str = 'une longue phrase qui pourrait contenir des caractères particuliers comme des "doubles guillemets"';
echo '{';
echo '"titre":"test",';
echo '"texte":"'.$str.'"';
echo '}';

Dans cet exemple, $str contient des guillemets doubles. Le JSON généré sera donc erroné. De plus, ça devient rapidement difficile à lire et corriger pour la maintenance du code.

On devrait donc écrire:

$str = 'une longue phrase qui pourrait contenir des caractères particuliers comme des "doubles guillemets"';
$data = array('titre' => 'test', 'texte' => $str);
echo json_encode($data);

Réponse HTTP

On devrait utiliser le type de contenu application/json ou text/json pour envoyer des réponses en HTTP.

$str = 'une longue phrase qui pourrait contenir des caractères particuliers comme des "doubles guillemets"';
$data = array('titre' => 'test', 'texte' => $str, 'liste'=>array(1,10,100,1000));

header('Content-type: application/json; charset=UTF-8');
echo json_encode($data);