Ajax, Json et compression Gzip
By Nicolas Crovatti on Saturday, February 23 2008, 19:13 - Ajax - Permalink
Dernièrement je me suis mis a utiliser intensivement le JSON (JavaScript Object Notation).
Le JSON est un mode léger d'échange de données que je trouve particulièrement adapté aux "XHR" (XmlHTTPRequest). Du coup les échanges avec les différents services ne se font plus en XML mais en JSON. Ce qui me fait poser la question : Dois-je maintenant parler de "JHR" (JsonHTTPRequest) ? Je ne sais pas, une chose est sûre ce format est beaucoup plus light que le XML.
De fait, les données sont aussi décrites comme en XML et on y gagne énormément en taille. Voici une comparaison :
En XML : <?xml version="1.0" encoding="UTF-8"?>
<links>
<link>
<title>moBlur.org</title>
<url>http://moblur.org/</url>
</link>
<link>
<title>moBlur.org - RSS</title>
<url>http://moblur.org/index.php?feed/rss2</url>
</link>
</links>
Le même message en JSON :
{"links": {
"link": [
{"title":"moBlur.org","url":"http://moblur.org/"},
{"title":"moBlur.org - RSS","url":"http://moblur.org/index.php?feed/rss2"}
]
}
}
Comparaison rapide de poids :
- XML : 256 bytes
- JSON : 168 bytes
<?php
function array2json($arr) {
$parts = array();
$is_list = false;
//Find out if the given array is a numerical array
$keys = array_keys($arr);
$max_length = count($arr)-1;
//See if the first key is 0 and last key is length - 1
if(($keys[0] == 0) and ($keys[$max_length] == $max_length)) {
$is_list = true;
//See if each key correspondes to its position
for($i=0; $i<count($keys); $i++) {
//A key fails at position check.
if($i != $keys[$i]) {
//It is an associative array.
$is_list = false;
break;
}
}
}
foreach($arr as $key=>$value) {
//Custom handling for arrays
if(is_array($value)) {
/* :RECURSION: */
if($is_list) $parts[] = array2json($value);
/* :RECURSION: */
else $parts[] = '"' . $key . '":' . array2json($value);
} else {
$str = '';
if(!$is_list) $str = '"' . $key . '":';
//Custom handling for multiple data types
if(is_numeric($value)) $str .= $value; //Numbers
elseif($value === false) $str .= 'false'; //The booleans
elseif($value === true) $str .= 'true';
//All other things
else $str .= '"' . addslashes($value) . '"';
$parts[] = $str;
}
}
$json = implode(',',$parts);
//Return numerical JSON
if($is_list) return '[' . $json . ']';
//Return associative JSON
return '{' . $json . '}';
}
?>
L'utilisation en combo du json et de cette fonction PHP nous facilite grandement la vie côté développement. J'utilise cette fonction de transformation en JSON uniquement dans mes fichiers web services, ceux qui s'occuppent de l'abstraction des données. Comme parfois il vaut mieux un petit dessin qu'un long discourt voici un diagramme de la solution structurelle que j'utilise dans tous mes développements dit "Web 2.0" :
Ce diagramme représente assez bien la quasi majorité des applications Web 2.0 je présume.
Après avoir lu pas mal d'informations sur le compactage des fichiers JavaScript notement ici (Cyril Durand) et là (Damien Ravé) et encore là (loogaroo.net), j'ai voulu enfoncer le clou et j'ai donc ajouté une compression Gzip avant d'envoyer le résultat JSON au client. Toutefois, pour des communications de faible taille, nous ne voudrons pas utiliser la compression Gzip car du principe même de la compression, si il y a trop peu de caractères le fait de compresser les données pourra éventuellement augmenter la taille de la transaction !
Voici une toute petite fonction PHP que j'utilise en conjonction Array2json() présentée plus haut :
<?php
$arr_json = array(
'link' => array(
array( 'link' => array(
'title' => 'moBlur.org',
'url' => 'http://moblur.org/'
),
array( 'link' => array(
'title' => 'moBlur.org - RSS',
'url' => 'http://moblur.org/index.php?feed/rss2'
)
)
)
);
print array2json($arr_json);
?>
Cette fonction compresse tout simplement les chaines de caractères avant de les renvoyer au client. Sur la durée on pourra voir une nette diminution de la bande passante consommée et un accroissement de la vitesse de communication entre votre serveur et vos clients Web. Tout le monde sera ravis, j'en suis sûr :)
Pour finir voici le diagramme final de notre architecture :


















