JSON - JavaScript Object Notation : Présentation
Par Pascal MARTIN le samedi 13 janvier 2007, 08:00 - Développement Web - Lien permanent
JSON est l'abréviation de "JavaScript Object Notation".
En quelques mots, JSON est une manière d'écrire des objets basée sur la syntaxe Javascript.
Le format JSON est défini par la RFC 4627, postée en Juillet 2006 par Douglas Crockford :
(extrait)
JavaScript Object Notation (JSON) is a text format for the serialization of structured data. It is derived from the object literals of JavaScript, as defined in the ECMAScript Programming Language Standard, Third Edition [ECMA].
(La traduction suivante est de moi)
La Notation Objet JavaScript est un format texte pour la sérialisation de données structurées. Il est dérivé des objets litéraux de JavaScript, tels qu'ils sont définis dans le Standard du Langage de Programmation ECMAScript, 3ème édition
Cela signifie que JSON est un format que l'on peut utiliser pour représenter des objets sous forme d'une chaîne de caractères, en utilisation une notation compatible avec JavaScript...
... le principal avantage étant que cette notation JavaScript permettra une manipulation aisée de ces objets sérialisés[1].
Données utilisant la Notation JavaScript Objet
Pour commencer, quelques mots sur la notation litéral objet de JavaScript, dont JSON est un sous-ensemble.
Déclarer un Objet
En JavaScript, un objet (simple, dans cet exemple) se déclare comme ceci :
var personne = { nom: 'Lerdorf', prenom: 'Rasmus' };
Et l'accès à ses propriétés se fait à l'aide de la syntaxe objet.propriete.
Par exemple, pour afficher le prénom et le nom de notre personne[2], nous pourrions écrire :
alert(personne.prenom + ' ' + personne.nom);
Ce qui afficherait effectivement :
Rasmus Lerdorf
Déclarer un tableau
En suivant la syntaxe de JavaScript, nous pouvons créer un tableau d'objets[3] :
var personnes = [ { nom: 'Lerdorf', prenom: 'Rasmus' }, { nom: 'Gutmans', prenom: 'Andi' }, { nom: 'Suraski', prenom: 'Zeev' } ];
Et l'accès à ses composantes se fait comme pour tout tableau/objet JavaScript.
Par exemple :
alert(personnes[1].prenom + ' ' + personnes[1].nom);
Affichera :
Andi Gutmans
JSON et données sérialisées
Savoir comment déclarer un objet en JavaScript, c'est bien... Mais ce n'est pas le but de cet article.
En effet, un objet JavaScript est propre au JavaScript : il ne peut pas être généré, ni n'est compréhensible, par d'autres langages.
Par contre, un chaîne de caractères, elle, est une notion commune à la plupart des langages de programmation.
Que donnerait un de nos objets une fois écrit sous forme d'une chaîne de caractères ?
Objet sérializé
En JavaScript, voici ce qu'on obtiendrait :
var strPersonne = "{nom: 'Lerdorf', prenom: 'Rasmus'}";
Nous avons juste entouré notre déclaration d'objet par des guillemets, et supprimé les espace d'indentation.
Et nous avons maintenant une chaîne de caractères JS valide :
alert(strPersonne);
Affichera :
{nom: 'Lerdorf', prenom: 'Rasmus'}
Ce qui n'est pas utilisable tel quel...
eval
Mais JavaScript propose une fonction nommée eval, qui permet d'exécuter du code stocké dans une chaîne de caractères.
Et JSON est un sous-ensemble de la notation litérale objet de JavaScript... ce qui signifie qu'il s'agit de code JS valide - et donc, evaluable.
Il faut juste rajouter des parenthèses autour de la déclaration d'objet, comme ceci :
var personne = eval('(' + strPersonne + ')');
Et personne sera exactement le même objet que le tout premier que nous avons présenté.
Ainsi,
alert(personne.prenom + ' ' + personne.nom);
affichera bien
Rasmus Lerdorf
Types de données JSON
JSON permet d'utiliser plusieurs types de données :
- Numérique : nombres entiers ou à virgule :
18,3.1415 - Chaîne de caractères : suite de caractères Unicode, encadrés par des guillemets doubles. Le caractère d'échappement est l'antislash[4] :
"Hello World","Retour\nà la ligne\tet tabulation" - Booléen :
trueoufalse - Tableau (Array) : Une liste ordonnées de valeurs, séparées par des virgules, et entourée de crochets :
[3.1415, 10, "coucou", true] - Objet : Collection de couples clef/valeur, séparés par des virgules, et entourée d'accolades :
{"pi": 3.1415, "mot": "coucou", "actif": true}. Les clefs sont des chaînes de caractères, donc, entre guillemets doubles[5]. null
Chaque valeur d'un tableau ou d'un objet peut être d'un de ces types.
Encore une fois, attention : les noms de propriétés d'objets sont des chaînes de caractères, donc, doivent être entourés de guillemets doubles ! Même si ce n'est pas nécessaire en JavaScript, ça l'est pour être conforme au format JSON !
Pour quelques illustrations, vous pouvez consulter la documentation en français de json.org.
JSON : Uniquement des données
Notation Litérale Objet JavaScript et méthodes
En utilisant la notation litérale d'objets de JavaScript, nous pouvons créer un objet représentant une personne habitant à Lyon et se nommant John Smith :
var personne = { nom: 'Smith', prenom: 'John', ville: 'Avignon', saluer: function (nom) { alert(this.prenom + ' ' + this.nom + ' salue ' + nom); }, demenager: function (nouvelleVille) { this.ville = nouvelleVille; alert(this.prenom + ' ' + this.nom + ' habite maintenant ' + this.ville); } };
Cette personne peut en saluer d'autre, et déménager.
Par exemple, pour saluer Bob, puis déménager à Lyon :
personne.saluer('Bob'); personne.demenager('Lyon');
Ce qui affichera successivement :
John Smith salue Bob
et :
John Smith habite maintenant Lyon
Et, bien entendu, la propriété ville de notre personne vaudra 'Lyon'.
JSON : un format d'échange de données
Cependant, JSON n'est qu'un sous-ensemble de la notation litérale d'objets de JavaScript, créé pour servir de format d'échange de données.
En conséquence, une chaîne de caractères au format JSON ne doit pas contenir de déclaration de méthode, mais uniquement des données.
La chaîne suivante (découpée uniquement pour des raisons de présentation, pour limiter le défilement horizontal) :
var strPersonne = '{"nom": "Smith", "prenom": "John", "ville": "Avignon", ' + '"saluer": function (nom) {alert(this.prenom + \' \' + this.nom + ' + '\' salue \' + nom);}, "demenager": function (nouvelleVille) ' + '{this.ville = nouvelleVille; alert(this.prenom + \' \' + ' + 'this.nom + \' habite maintenant \' + this.ville);}}';
(oui, les guillemets doubles tout le long ne simplifient pas la lecture... Mais ils sont requis par la spécification JSON)
... passe parfaitement si on l'appelle avec eval :
var personne = eval('(' + strPersonne + ')'); personne.saluer('Bob'); personne.demenager('Lyon');
... et elle causera les deux mêmes affichages que précédemment.
Mais ce n'est pas une chaîne de caractères JSON valide, puisqu'elle contient des définitions de méthodes - ceci, pour raisons de sécurité : si vous vous assurez qu'une chaîne est du JSON valide avant de l'evaluer, vous saurez que l'objet obtenu ne contient que des données, et pas de méthode.
Autrement dit, en validant une chaîne de caractères JSON avant de l'évaluer, vous protégez votre application contre d'éventuelles injections de méthodes.
Validation de données JSON
Pour valider qu'une chaîne est du JSON valide avant de l'évaluer, utilisez le code suivant (donné en exemple au sein de la RFC 4627 évoquée plus haut) :
var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/|>.test( text.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + text + ')');
Pour être averti lors de la publication de nouvelles entrées, n'hésitez pas à vous abonner au flux RSS ou ATOM des articles de mon blog !
Commentaires
C'est un test avec des accents éèêà
JSON.parse(Text); // JSON.parse is more secure with non trusted data. need of json2.js
Article très utile. Dommage que ce blog ne soit plus réactualisé depuis plusieurs mois.
S.
Merci
Effectivement, dommage que je n'aie pas tellement eu de temps ces derniers mois
Je suis en ce moment très pris avec des projets non PHP/Javascript, et, donc, peu en rapport avec ce blog...
Mais, avec un peu de chance, dans quelques temps, j'aurais suffisament avancé sur les projets en question, qui me prendront alors moins de temps ; et je pourrai re-passer un peu de temps sur ce blog (ça me manque un peu, mine de rien...).
Bonsoir,
j'ai écrit la fonction suivante :
Object.prototype.isin=function()
{
for(var j in arguments0) if(arguments0j===this) return true
return false
}
pour déterminer si quelque chose est dans autre chose.
Or, si je fait :
tagname='INPUT'
tagname.isin('INPUT','TEXTAREA')
cela renvoie : false.
En effet :
Object.prototype.isin=function()
{
for(var j in arguments0)
{
alert(typeof arguments0j) // 'string'
alert(typeof this) // 'object'
}
}
Une suggestion ?
Merci.
Merci pour toutes ces précisions sur les objets JSON!