L'interaction avec les serveurs via AJAX pour récupérer des données structurées, notamment en format JSON, est une pratique courante dans le développement web moderne. Ce document explore les subtilités de la configuration côté serveur et client pour assurer une communication fluide.
Scénario avec Servlet Java : Gestion des données brutes
Initialement, considérons un scénario où un Servlet Java renvoie une chaîne de caractères représentant une structure JSON, sans définir explicitemant le type de contenu de la réponse. Cette approche, bien que fonctionnelle dans certains contextes, peut entraîner des problèmes lors de l'utilisation de méthodes de requête plus spécifiques.
String rawData = "["+
"{ id:1, pId:0, name:\"Nœud parent pliable 1\", t:\"Je suis ordinaire, amusez-vous à me déplier/replier\", open:false},"+
"{ id:11, pId:1, name:\"Nœud feuille - 1\", t:\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ id:12, pId:1, name:\"Nœud parent pliable 2\", t:\"Mon père et moi sommes ordinaires, amusez-vous avec nous\", open: false},"+
"{ id:121, pId:12, name:\"Nœud parent - 121\", t:\"Mon père est ordinaire, amusez-vous avec lui\", open:true},"+
"{ id:1211, pId:121, name:\"Nœud parent - 1211\", t:\"Mon père est ordinaire, amusez-vous avec lui\", open:false},"+
"{ id:1212, pId:1211, name:\"Nœud feuille - 1212\", t:\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ id:1213, pId:121, name:\"Nœud parent - 1213\", t:\"Mon père est ordinaire, amusez-vous avec lui\", open:false},"+
"{ id:1214, pId:1213, name:\"Nœud feuille - 1214\", t:\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ id:123, pId:12, name:\"Nœud feuille - 23\", t:\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ id:13, pId:1, name:\"Nœud feuille - 3\", t:\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ id:2, pId:1, name:\"Nœud parent non repliable\", t:\"Ne pensez pas me replier... sauf si vous utilisez expandAll\", open:false, collapse:false},"+
"{ id:21, pId:2, name:\"Nœud feuille 2 - 1\", t:\"Haha, mon père est cool, impossible de le replier ?\"},"+
"{ id:22, pId:21, name:\"Nœud feuille 2 - 2\", t:\"Haha, mon père est cool, impossible de le replier ?\"},"+
"{ id:23, pId:21, name:\"Nœud feuille 2 - 3\", t:\"Haha, mon père est cool, impossible de le replier ?\"},"+
"{ id:3, pId:2, name:\"Nœud parent non déployable\", t:\"Vous pensez pouvoir me déployer ? Difficile... sauf si vous utilisez expandAll\", open:false, expand:true},"+
"{ id:31, pId:3, name:\"Nœud feuille 3 - 1\", t:\"Vous m'avez vu... Avez-vous utilisé expandAll ?\"},"+
"{ id:32, pId:31, name:\"Nœud feuille 3 - 2\", t:\"Vous m'avez vu... Avez-vous utilisé expandAll ?\"},"+
"{ id:33, pId:31, name:\"Nœud feuille 3 - 3\", t:\"Vous m'avez vu... Avez-vous utilisé expandAll ?\"},"+
"{ id:4, pId:3, name:\"Nœud parent vide 1\", t:\"Je n'ai rien... sauf moi-même\", isParent:true, open:false}"+
"]";
Client : Utilisaiton de $.post
Lorsque le frontend utilise $.post pour récupérer ces données, la méthode traite la réponse comme du texte brut et utilise eval() pour la convertir en objet JavaScript. Cela fonctionne sans problème pour initialiser une structure d'arbre.
$.post('/ServletEndpoint', {}, function(responseData) {
var treeData = eval("(" + responseData + ")");
$.fn.zTree.init($("#treeContainer"), treeSettings, treeData);
});
Client : Utilisation de $.ajax avec dataType: "json"
Cependant, l'utilisation de $.ajax avec la directive dataType: "json" échoue dans ce même scénario. Le navigateur, s'attendant à recevoir du JSON valide, ne parvient pas à interpréter la réponse textuelle mal formée, entraînant une erreur de chargement.
$.ajax({
type: "POST",
url: '/ServletEndpoint',
timeout: 1000,
data: {
param1: "valeur1",
param2: "valeur2"
},
async: true,
dataType: "json", // Indique au client d'attendre du JSON
error: function() {
alert("La requête a échoué !");
},
success: function(parsedData) {
// Cette partie ne sera pas atteinte si le JSON n'est pas valide
treeObject = $.fn.zTree.init($("#treeContainer"), treeSettings, parsedData);
}
});
Solution : Structuration correcte des données côté serveur
Pour que les requêtes AJAX spécifiant dataType: "json" fonctionnent correctemetn, il est impératif que le serveur renvoie des données JSON syntaxiquement valides. Cela implique d'ajouter des guillemets autour des clés (noms des propriétés).
String properlyFormattedJson = "["+
"{ \"id\":1, \"pId\":0, \"name\":\"Nœud parent pliable 1\", \"t\":\"Je suis ordinaire, amusez-vous à me déplier/replier\", \"open\":false},"+
"{ \"id\":11, \"pId\":1, \"name\":\"Nœud feuille - 1\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ \"id\":12, \"pId\":1, \"name\":\"Nœud parent pliable 2\", \"t\":\"Mon père et moi sommes ordinaires, amusez-vous avec nous\", \"open\": false},"+
"{ \"id\":121, \"pId\":12, \"name\":\"Nœud parent - 121\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\", \"open\":true},"+
"{ \"id\":1211, \"pId\":121, \"name\":\"Nœud parent - 1211\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\", \"open\":false},"+
"{ \"id\":1212, \"pId\":1211, \"name\":\"Nœud feuille - 1212\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ \"id\":1213, \"pId\":121, \"name\":\"Nœud parent - 1213\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\", \"open\":false},"+
"{ \"id\":1214, \"pId\":1213, \"name\":\"Nœud feuille - 1214\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ \"id\":123, \"pId\":12, \"name\":\"Nœud feuille - 23\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ \"id\":13, \"pId\":1, \"name\":\"Nœud feuille - 3\", \"t\":\"Mon père est ordinaire, amusez-vous avec lui\"},"+
"{ \"id\":2, \"pId\":1, \"name\":\"Nœud parent non repliable\", \"t\":\"Ne pensez pas me replier... sauf si vous utilisez expandAll\", \"open\":false, \"collapse\":false},"+
"{ \"id\":21, \"pId\":2, \"name\":\"Nœud feuille 2 - 1\", \"t\":\"Haha, mon père est cool, impossible de le replier ?\"},"+
"{ \"id\":22, \"pId\":21, \"name\":\"Nœud feuille 2 - 2\", \"t\":\"Haha, mon père est cool, impossible de le replier ?\"},"+
"{ \"id\":23, \"pId\":21, \"name\":\"Nœud feuille 2 - 3\", \"t\":\"Haha, mon père est cool, impossible de le replier ?\"},"+
"{ \"id\":3, \"pId\":2, \"name\":\"Nœud parent non déployable\", \"t\":\"Vous pensez pouvoir me déployer ? Difficile... sauf si vous utilisez expandAll\", \"open\":false, \"expand\":true},"+
"{ \"id\":31, \"pId\":3, \"name\":\"Nœud feuille 3 - 1\", \"t\":\"Vous m'avez vu... Avez-vous utilisé expandAll ?\"},"+
"{ \"id\":32, \"pId\":31, \"name\":\"Nœud feuille 3 - 2\", \"t\":\"Vous m'avez vu... Avez-vous utilisé expandAll ?\"},"+
"{ \"id\":33, \"pId\":31, \"name\":\"Nœud feuille 3 - 3\", \"t\":\"Vous m'avez vu... Avez-vous utilisé expandAll ?\"},"+
"{ \"id\":4, \"pId\":3, \"name\":\"Nœud parent vide 1\", \"t\":\"Je n'ai rien... sauf moi-même\", \"isParent\":true, \"open\":false}"+
"]";
En plus de cela, le Servlet doit explicitement indiquer au client qu'il renvoie du JSON en définissant l'en-tête Content-Type.
response.setContentType("application/json; charset=utf-8");
// Ici, écrivez properlyFormattedJson dans le flux de sortie de la réponse
En résumé, lorsque vous utilisez AJAX avec dataType: "json", assurez-vous que le serveur renvoie des données JSON syntaxiquement correctes, y compris des clés entourées de guillemets, et qu'il définit l'en-tête Content-Type approprié.