Utiliser JSON comme format d'échange de données, avec prototype.js
27 janvier 2007 —Nous avons vu comment réaliser une première requête Ajax en utilisant prototype.js, et comment utiliser JSON comme format d'échanges de données lors d'une requête Ajax utilisant directement l'objet XMLHttpRequest.
A présent, nous allons voir comment nous pouvons mettre ces connaissances "en commun", et utiliser JSON comme format d'échange de données lorsque l'on développe avec le framework Prototype.
Principe de fonctionnement
Un bref rappel sur le principe de fonctionnement :
- Une page HTML contenant, pour notre exemple, un lien appelant une fonction nommée
gestionClic
, qui sera chargée de lancer la requête Ajax et gérer son retour. - Quelques lignes de JavaScript, réalisant l'appel Ajax et obtenant la réponse du serveur.
- Et un programme côté serveur (encore une fois, j'utiliserai du PHP), chargé du traitement déclenché par la requête Ajax.
Puisque c'est le but de cet article, le format de données utilisé en sortie par le programme côté serveur sera JSON.
Page HTML
Pour commencer, voici à quoi peut ressembler notre page HTML :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>AJAX : Exemple de client</title>
<script type="text/javascript" src="prototype-1.5.0.js"></script>
<script type="text/javascript" src="test2.js"></script>
</head>
<body>
<p>
<a href="" onclick="gestionClic(); return false;">
Cliquez ici !
</a>
</p>
<div id="resultat"> </div>
</body>
</html>
Et la fonction gestionClic
, appelée lors d'un clic sur le lien, peut être la suivante :
function gestionClic()
{
var url = './test2.php';
var myAjax = new Ajax.Request(
url,
{
method: 'get',
onComplete: gestionReponse
});
} // gestionClic()
En cas de clic sur le lien, une requête HTTP est envoyée en GET à la page test2.php.
Une fois la réponse reçue, la fonction gestionReponse
est automatiquement appelée pour la traiter.
Par la suite, nous allons travailler au développement de cette fonction.
JSON en responseText
Nous avons vu lors d'un précédent article que l'on peut, avec le programme côté serveur, écrire des données JSON sur la sortie standard ; par exemple, pour renvoyer la liste de trois des noms de trois auteurs de PHP :
<?php
header('Content-Type: text/html; charset: UTF-8');
echo '[{"nom": "Lerdorf", "prenom": "Rasmus"}, {"nom": "Gutmans", "prenom": "Andi"}, {"nom": "Suraski", "prenom": "Zeev"}]';
?>
Ce qui est écrit sur la sortie standard du programme serveur est reçu comme corps de la réponse HTTP, et est accessible via la propriété responseText
de l'object XMLHttpRequest.
L'instance d'objet XHR utilisé pour effectuer la requête Ajax est passé par prototype.js en premier paramètre de la fonction appelée à la fin de celle-ci.
En eval
uant le contenu de la propriété responseText
de cet objet, on reconstitue, côté JavaScript, l'objet renvoyé par le serveur.
Par exemple, pour afficher les noms des trois personnes renvoyées par le programme PHP présenté juste au-dessus :
function gestionReponse(xhr)
{
var personnes = eval('(' + xhr.responseText + ')');
if (personnes)
{
var str = '';
for (var i=0 ; i < personnes.length ; i++)
{
var personne = personnes[i];
str += personne.prenom + ' '
+ personne.nom + '<br />';
}
$('resultat').innerHTML = str;
}
}
Nous commençons par eval
uer les données au format JSON renvoyée par le serveur, puis, si cette eval
uation s'est bien passée - la liste des personnes n'est pas vide - nous parcourons la liste, en vue d'obtenir les noms et prénoms de chacun... Et pour finir, nous affichons le résultat.
Ce qui affichera, comme attendu :
Rasmus Lerdorf
Andi Gutmans
Zeev Suraski
Mais le framework prototype.js permet d'automatiser ces traitements, afin de diminuer votre charge de travail...
Prototype.js et JSON
Prototype.js permet d'automatiser un peu ceci : si la réponse HTTP contient un en-tête nommé X-JSON, le contenu de celui-ci sera extrait, automatiquement eval
ué, et sauvegardé comme un objet.
Cet objet sera alors passé en second paramètre à la fonction déclenchée à la réception du résultat - notre fonction gestionReponse
.
Code PHP
A titre d'exemple, voici le code d'un programme PHP écrivant notre liste d'auteurs dans un en-tête HTTP nommé X-JSON
, plutôt que sur la sortie standard :
<?php
header('Content-Type: text/html; charset: UTF-8');
$str = '[{"nom": "Lerdorf", "prenom": "Rasmus"}, {"nom": "Gutmans", "prenom": "Andi"}, {"nom": "Suraski", "prenom": "Zeev"}]';
header('X-JSON: ' . $str);
?>
Récupération et utilisation des données
Et côté JavaScript :
- Le second paramètre reçu par la méthode de gestion de la réponse est l'objet reconstitué.
- Nous pouvons l'utiliser comme si nous avions appelé
eval
nous même. - Il ne faut pas appeler
eval
nous-même sur les données de l'en-têteX-JSON
: cela reviendrait à l'appeler deux fois, puisqu'il est déjà exécuté par prototype.js, ce qui causerait une perte de temps et de performances !
Pour exemple (notez la présence du second paramètre) :
function gestionReponse(xhr, personnes)
{
if (personnes)
{
var str = '';
for (var i=0 ; i < personnes.length ; i++)
{
var personne = personnes[i];
str += personne.prenom + ' '
+ personne.nom + '<br />';
}
$('resultat').innerHTML = str;
}
}
Nous commençons par vérifier que l'objet a bien été eval
ué ; et si oui, nous l'utilisons, exactement comme nous l'avons fait plus haut.
Pour information, plutôt que de parcourir la liste de personnes "à la main", nous pouvons exploiter le fait que, lorsque l'on utilise prototype.js, les listes sont automatiquement étendues en objets Enumerable.
Cela signifie, entre autre, qu'on peut les parcourir à l'aide de la méthode each
, qui permet d'exécuter une fonction sur chaque élément de la liste :
function gestionReponse(xhr, personnes)
{
var str = '';
personnes.each(
function (personne)
{
str += personne.prenom + ' '
+ personne.nom + '<br />';
});
$('resultat').innerHTML = str;
}
Pour plus d'informations à ce sujet, n'hésitez par à consulter la documentation de l'API de prototype.js !
Évaluation automatique de JavaScript
Il reste encore une fonctionnalité de prototype.js dont je souhaite parler dans cet article :
Si le Content-Type de la réponse renvoyée par le serveur est un de ceux que prototype.js reconnaît comme indiquant du JavaScript, alors, le code retourné sera automatiquement eval
ué.
Cela signifie deux choses :
- Le code JS renvoyé par le serveur sera exécuté (Je l'ai déjà dit juste en-dessous, mais c'est suffisament important et/ou impactant - ne serait-ce qu'en terme de sécurité - pour que j'insiste).
- Vous n'avez pas besoin de gérer vous-même la réponse à votre requête.
Par exemple, si le code de votre programme côté serveur, appelé par votre requête Ajax, est le suivant :
<?php
header('Content-Type: text/javascript; charset: UTF-8');
echo "alert('bouh !');";
?>
Le Content-Type renvoyé par le serveur sera "text/javascript" - qui est l'un de ceux reconnus par prototype.js.
En admettant que votre appel soit fait de la manière suivante :
function gestionClic()
{
var url = './test2.php';
var myAjax = new Ajax.Request(
url,
{
method: 'get'
});
} // gestionClic()
Le code alert('bouh !');
sera exécuté au retour de la requête... Un message s'affichera à l'utilisateur.
Note : Si tout ce que nous voulons faire est exécuter le code JavaScript généré par le serveur, il n'est même pas nécessaire de définir une fonction gérant le retour de la requête (branchée sur l'événement onComplete
, par exemple) ; c'est ce que j'ai fait ici, d'ailleurs.
Liste des Content-Type reconnus par prototype.js
Pour que les données renvoyées par le serveur soient interprétée comme étant du code JavaScript, et que celui-ci soit eval
ué, le Content-Type de la réponse HTTP doit être un des suivants :
application/ecmascript
application/javascript
application/x-ecmascript
application/x-javascript
text/ecmascript
text/javascript
text/x-ecmascript
text/x-javascript
Je n'ai jusqu'à présent encore jamais réellement utilisé la fonctionnalité d'évaluation automatique de code JavaScript... Mais l'évaluation automatique de données JSON, par contre, elle, est un réel plus ; nous serons sans aucun doute amenés à l'utiliser à l'avenir, au cours de futurs articles.
MAJ 03/04/2008 : Ajout en pièce jointe à l'article d'une archive contenant un exemple complet