Bonjour à tous
Suite à quelques discussions sur des sujets voisins, voici quelques éléments sur le transport de données via JSON.
JSON est à la base une notation directement issue de javascript. Elle s'est émancipée de cette origine mais en garde tout de même des traces.
Les types transportés par JSON sont les types de base de javascript : String, Number, Boolean et les types structurés Array et Object.
JSON ne prévoit pas de typer plus fortement les données transmises.
Pas de date, char (date est une classe qui est dans le moteur JS mais pas dans le langage)
Encore moins de structure définie par l'utilisateur ni de classes (Javascript n'est pas un langage à base de classe mais un langage à prototype, donc on peut lui ajouter mais ce n'est pas dans sa nature)
Du coup il n'y a rien de précis sur le sujet.
Mais certains utilisent JSON pour inclure des informations de type.
La principale que j'ai trouvée consiste à inclure des noms de classe.
J'ai trouvé deux écoles : la première vient du monde java. Elle consiste à ajouter en "root élément" le nom de la classe
{"MyPojo":{"id":4, "name":"test"}}
C'est simple mais du coup la structure est changée. Là un un AJAX attendaitil reçoit un niveau hiérarchique de plus.
Côté PHP (Zend en autre) la solution proposée consiste à ajouter un membre de plus à l'objet
{"__ClassName":"MyPojo","id":4, "name":"test"}
Cela implique que l'objet ne peut avoir un membre __ClassName.
C'est la même approche qu'utilise objective j mais avec une clef différente
{"__objjClassName":"MyPojo","id":4, "name":"test"}
j'ai trouvé un exemple (non public désolé) qui code aussi les types mais ça devient lourd
{"o":"MyPojo":[{"s":"id", "i":45},{"s":"name", "s":"test"};]}
o pour object, i pour int s pour string etc
Dans ce cas il faut écrire un parseur spécifique pour récupérer son info car il ne contient pas le JSON "standard" dans ses parties.
Cette solution est très proche de php serialize
O:6:"MyPojo":2:{s:2:"id";i:45;s:4:"name";s:4:"test";}
Dans le même ordre d'idées mais en mixant les deux approches on peut envisager de transporter la description des types dans un membre et les données ensuite. Mais je n'ai rien trouvé de tel
1 2
| {"__Types":{"O":{"ClassName":"MyPojo",{"i":"id","s":"name"}}},
"id":4, "name":"test"} |
Tout cela ajoute de la lourdeur et de la complexité. Comment traiter une description dont les donnée ne correspondent pas, un int à la place d'un string par exemple etc.
Enfin pour finir une autre approche du problème est d'en passer par un schéma. Tout comme un XML se décrit par un xsd un JSON peut être décrit par un schéma lui même définit en JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| {"complexType":{
"name":"MyPojo",
"all":[
{"element" {"name":"id", "type":"integer"}}
{"element" {"name":"name", "type":"string" }}
{"element" {
"name":"date",
"type":"Date",
"restriction":{
"base":"string",
"pattern":{"value":"[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}:[0-9]{3}"}
}
}}
]
}} |
Ce schéma étant chargé une seule fois indépendamment des données pour permettre au parser de faire des vérification plus strictes
L'utilisation d'une notation comme
{"__ClassName":"MyPojo","id":4, "name":"test", "date":"2010-11-22 10:58:12:532"}
devenant suffisante pour typer plus fortement les données.
Bien sûr tout cela n'est pas normalisé et est un peu à l'opposé de la philosophie de base de JSON qui est par nature (très) faiblement typé
La solution "root élément" est facile à implémenter côté serveur et nécessite une adaptation côté client pour récupérer les donnes.
la solution "membre" est facile à mettre en œuvre côté serveur et est ignorée par Ajax, elle ne nécessite une adaptation côté client que si l'on veut exploiter les noms de classe.
Les deux ne typent pas les membres.
La solution que j'ai trouvée qui ressemble à php sérialize est plus complexe à mettre en œuvre côté serveur et me parait très complexe côté client. Elle nécessite d'écrire un PostParser qui après le parser JSON reconstruit l'objet final.
La solution mixte que j'ai extrapolée dans cet article est presque aussi lourde mais moyennant une petite adaptation on peut récupérer les données comme dans un JSON standard. Je ne voit pas l'utilité de faire cela.
Transporter le type dans les données est pour moi contre-productif, lourd et complexe.
Je pense que si l'on a un besoin de typage fort une description genre schéma (voire plus simple) me paraît plus appropriée car elle n'influence pas ou peu le trafic. Extjs utilise ce genre de description:
1 2 3 4 5 6 7
| {fields: [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
]} |
A+JYT
Partager