Introduction à JavaScript Object Notation (JSON) en JavaScript et .NET

 

Introduction à JavaScript Object Notation (JSON) en JavaScript et .NET

Atif Aziz, Scott Mitchell

Février 2007

S’applique à :
   JSON
   Ajax

Résumé: Cet article décrit javaScript Object Notation (ou JSON), un format d’échange de données ouvert et textuel, qui fournit un format d’échange de données standardisé mieux adapté aux applications web de style Ajax. (22 pages imprimées)

Contenu

Introduction
Présentation de la notation littérale en JavaScript
Comparaison de JSON à XML
Création et analyse de messages JSON avec JavaScript
Utilisation de JSON dans le .NET Framework
Conclusion
Références

Téléchargez le code source de cet article.

Introduction

Lors de la conception d’une application qui communiquera avec un ordinateur distant, un format de données et un protocole d’échange doivent être sélectionnés. Il existe une variété d’options ouvertes et standardisées, et le choix idéal dépend des exigences des applications et des fonctionnalités préexistantes. Par exemple, les services web soap mettez en forme les données dans une charge utile XML encapsulée dans une enveloppe SOAP.

Bien que XML fonctionne bien pour de nombreux scénarios d’application, il présente certains inconvénients qui le rendent moins idéal pour d’autres. L’un de ces espaces où XML n’est souvent pas idéal est celui des applications web de style Ajax. Ajax est une technique utilisée pour créer des applications web interactives qui fournissent une expérience utilisateur plus précise grâce à l’utilisation d’appels légers et hors bande au serveur web au lieu de publications de page complète. Ces appels asynchrones sont lancés sur le client à l’aide de JavaScript et impliquent la mise en forme des données, leur envoi à un serveur web, ainsi que l’analyse et l’utilisation des données retournées. Bien que la plupart des navigateurs puissent construire, envoyer et analyser du code XML, JavaScript Object Notation (ou JSON) fournit un format d’échange de données standardisé mieux adapté aux applications web de style Ajax.

JSON est un format d’échange de données texte ouvert (voir RFC 4627). Comme XML, il est lisible par l’homme, indépendant de la plateforme et bénéficie d’une grande disponibilité des implémentations. Les données mises en forme selon la norme JSON sont légères et peuvent être analysées par les implémentations JavaScript avec une facilité incroyable, ce qui en fait un format d’échange de données idéal pour les applications web Ajax. Étant donné qu’il s’agit principalement d’un format de données, JSON n’est pas limité aux applications web Ajax et peut être utilisé dans pratiquement tous les scénarios où les applications doivent échanger ou stocker des informations structurées sous forme de texte.

Cet article examine la norme JSON, sa relation avec JavaScript et comment elle se compare à XML. Jayrock, une implémentation JSON open source pour .NET, est abordé et des exemples de création et d’analyse de messages JSON sont fournis en JavaScript et C#.

Présentation de la notation littérale en JavaScript

Les littéraux sont utilisés dans les langages de programmation pour exprimer littéralement des valeurs fixes, telles que la valeur entière constante de 4 ou la chaîne « Hello, World ». Les littéraux peuvent être utilisés dans la plupart des langages où une expression est autorisée, par exemple dans le cadre d’une condition dans une instruction de contrôle, un paramètre d’entrée lors de l’appel d’une fonction, dans l’attribution de variable, etc. Par exemple, le code C# et Visual Basic suivant initialise la variable x avec la valeur entière constante de 42.

  
    int x = 42;  // C#
Dim x As Integer = 42  ' Visual Basic
  

Différents langages de programmation permettent d’utiliser des littéraux de types différents. La plupart des langages de programmation prennent en charge, au minimum, les littéraux pour les types scalaires tels que les entiers, les nombres à virgule flottante, les chaînes et les booléens. Ce qui est intéressant avec JavaScript, c’est qu’en plus des types scalaires, il prend également en charge les littéraux pour les types structurés comme les tableaux et les objets. Cette fonctionnalité permet une syntaxe terse pour la création et l’initialisation à la demande de tableaux et d’objets.

Les littéraux de tableau en JavaScript sont composés de zéro ou plusieurs expressions, chaque expression représentant un élément du tableau. Les éléments du tableau sont placés entre crochets ([]) et délimités par des virgules. L’exemple suivant définit un tableau littéralement avec sept éléments de chaîne contenant les noms des sept continents :

  
    var continents = ["Europe", "Asia", "Australia", "Antarctica", "North
 America", "South America", "Africa"];
alert(continents[0] + " is one of the " + continents.length + "
 continents.");
  

Comparez ceci maintenant à la façon dont vous créeriez et initialiseriez un tableau en JavaScript sans la notation littérale :

  
    var continents = new Array();
continents[0] = "Europe";
continents[1] = "Asia";
continents[2] = "Australia";
continents[3] = "Antarctica";
continents[4] = "North America";
continents[5] = "South America";
continents[6] = "Africa";
  

Un littéral d’objet définit les membres d’un objet et leurs valeurs. La liste des membres et des valeurs de l’objet est entourée d’accolades ({}) et chaque membre est délimité par une virgule. Dans chaque membre, le nom et la valeur sont délimités par un signe deux-points (:). L’exemple suivant crée un objet et l’initialise avec trois membres nommés Address, City et PostalCode avec les valeurs respectives « 123 Anywhere St. », « Springfield » et « 99999 ».

  
    var mailingAddress = { 
     "Address"    :   "123 Anywhere St.", 
     "City"       :   "Springfield", 
     "PostalCode" :   99999
};
alert("The package will be shipped to postal code " +
 mailingAddress.PostalCode);
  

Les exemples présentés jusqu’à présent illustrent l’utilisation de littéraux de chaîne et de littéraux numériques dans des littéraux de tableau et d’objet. Vous pouvez également exprimer un graphe entier à l’aide de la notation de manière récursive afin que les éléments de tableau et les valeurs membres de l’objet puissent eux-mêmes utiliser eux-mêmes des littéraux d’objet et de tableau. Par exemple, l’extrait de code suivant illustre un objet qui a un tableau en tant que membre (PhoneNumbers), où le tableau est composé d’une liste d’objets.

  
    var contact = {
     "Name": "John Doe",
     "PermissionToCall": true,
     "PhoneNumbers": [ 
       {
           "Location": "Home",
           "Number": "555-555-1234"
       },
       {
           "Location": "Work",
           "Number": "555-555-9999 Ext. 123"
       }
     ]
};
if (contact.PermissionToCall)
{
  alert("Call " + contact.Name + " at " + contact.PhoneNumbers[0].Number);
}
  

Note Vous trouverez une description plus approfondie de la prise en charge littérale de JavaScript dans le Guide JavaScript 1.5 de base sous la section Littéraux.

Des littéraux JavaScript vers JSON

JSON est un format d’échange de données créé à partir d’un sous-ensemble de la notation d’objet littérale en JavaScript. Bien que la syntaxe acceptée par JavaScript pour les valeurs littérales soit très flexible, il est important de noter que JSON a des règles beaucoup plus strictes. Selon la norme JSON, par exemple, le nom d’un membre d’objet doit être une chaîne JSON valide. Une chaîne au format JSON doit être placée entre guillemets. JavaScript, en revanche, permet aux noms des membres d’objet d’être délimités par des guillemets ou des apostrophes, ou d’omettre complètement les guillemets tant que le nom de membre n’est pas en conflit avec un mot clé JavaScript réservé. De même, un élément de tableau ou une valeur de membre d’objet dans JSON est limité à un ensemble très limité. En JavaScript, toutefois, les éléments de tableau et les valeurs des membres d’objet peuvent faire référence à pratiquement n’importe quelle expression JavaScript valide, y compris les appels de fonction et les définitions .

Le charme de JSON réside dans sa simplicité. Un message mis en forme selon la norme JSON est composé d’un seul objet ou tableau de niveau supérieur. Les éléments de tableau et les valeurs d’objet peuvent être des objets, des tableaux, des chaînes, des nombres, des valeurs booléennes (true et false) ou null. Voilà, en un mot, la norme JSON ! Cette opération est très simple. Pour obtenir une description plus formelle de la norme , consultez www.json.org ou RFC 4627 .

L’un des points douloureux de JSON est l’absence d’un littéral date/heure. De nombreuses personnes sont surprises et déçues d’apprendre cela lorsqu’elles rencontrent JSON pour la première fois. L’explication simple (consolante ou non) de l’absence d’un littéral date/heure est que JavaScript n’en a jamais eu non plus : la prise en charge des valeurs de date et d’heure dans JavaScript est entièrement fournie via l’objet Date . Par conséquent, la plupart des applications utilisant JSON comme format de données ont généralement tendance à utiliser une chaîne ou un nombre pour exprimer des valeurs de date et d’heure. Si une chaîne est utilisée, vous pouvez généralement vous attendre à ce qu’elle soit au format ISO 8601. Si un nombre est utilisé, à la place, la valeur est généralement prise pour indiquer le nombre de millisecondes en temps universel coordonné (UTC) depuis l’époque, où l’époque est définie comme minuit le 1er janvier 1970 (UTC). Là encore, il s’agit d’une simple convention qui ne fait pas partie de la norme JSON. Si vous échangez des données avec une autre application, vous devez case activée sa documentation pour voir comment elle encode les valeurs de date et d’heure dans un littéral JSON. Par exemple, ASP.NET AJAX de Microsoft n’utilise aucune des conventions décrites. Au lieu de cela, il encode les valeurs .NET DateTime sous la forme d’une chaîne JSON, où le contenu de la chaîne est \/Date(ticks)\/ et où les graduations représentent des millisecondes depuis l’époque (UTC). Ainsi, le 29 novembre 1989, 4:55:30 AM, en UTC est encodé en tant que « \/Date(628318530718)\/ ». Pour une raison d’être derrière ce choix d’encodage plutôt artificiel, consultez « À l’intérieur de ASP.NET chaîne de date et d’heure JSON d’AJAX ».

Comparaison de JSON à XML

Json et XML peuvent être utilisés pour représenter des objets natifs en mémoire dans un format d’échange de données textuel, lisible par l’homme. En outre, les deux formats d’échange de données sont isomorphes: le texte étant donné dans un format, un format équivalent est concevable dans l’autre. Par exemple, lorsque vous appelez l’un des services web accessibles publiquement de Yahoo!, vous pouvez indiquer via un paramètre de chaîne de requête si la réponse doit être mise en forme au format XML ou JSON. Par conséquent, lorsque vous décidez d’un format d’échange de données, il ne s’agit pas simplement de choisir l’un plutôt que l’autre comme solution miracle, mais plutôt quel format a les caractéristiques qui en font le meilleur choix pour une application particulière. Par exemple, XML a ses racines dans le marquage du texte du document et a tendance à briller très bien dans cet espace (comme cela est évident avec XHTML). Json, d’autre part, trouve ses racines dans les types et structures de langage de programmation et fournit donc un mappage plus naturel et facilement disponible pour échanger des données structurées. Au-delà de ces deux points de départ, le tableau suivant vous aidera à comprendre et à comparer les principales caractéristiques de XML et JSON.

Principales différences de caractéristiques entre XML et JSON

Caractéristique XML JSON
Types de données Ne fournit aucune notion de types de données. Vous devez vous appuyer sur le schéma XML pour ajouter des informations de type. Fournit des types de données scalaires et la possibilité d’exprimer des données structurées via des tableaux et des objets.
Prise en charge des tableaux Les tableaux doivent être exprimés par des conventions, par exemple à l’aide d’un élément d’espace réservé externe qui modélise le contenu des tableaux en tant qu’éléments internes. En règle générale, l’élément externe utilise la forme plurielle du nom utilisé pour les éléments internes. Prise en charge du tableau natif.
Prise en charge des objets Les objets doivent être exprimés par des conventions, souvent par le biais d’une utilisation mixte d’attributs et d’éléments. Prise en charge des objets natifs.
Prise en charge de Null Nécessite l’utilisation de xsi:nil sur les éléments d’un document xml instance plus une importation de l’espace de noms correspondant. Reconnaît en mode natif la valeur Null .
Commentaires Prise en charge native et généralement disponible via les API. Non pris en charge.
Espaces de noms Prend en charge les espaces de noms, ce qui élimine le risque de collisions de noms lors de la combinaison de documents. Les espaces de noms permettent également d’étendre en toute sécurité les normes xml existantes. Aucun concept d’espace de noms. Les collisions de nommage sont généralement évitées en imbriquant des objets ou en utilisant un préfixe dans un nom de membre d’objet (le premier est préférable dans la pratique).
Décisions de mise en forme Complexe. Nécessite davantage d’efforts pour décider comment mapper des types d’application aux éléments et attributs XML. Peut créer des débats animés si une approche centrée sur les éléments ou sur les attributs est meilleure. Simplement. Fournit un mappage beaucoup plus direct pour les données d’application. La seule exception peut être l’absence de littéral date/heure.
Taille Les documents ont tendance à être de taille longue, en particulier lorsqu’une approche de mise en forme centrée sur les éléments est utilisée. La syntaxe est très terse et génère du texte mis en forme où la majeure partie de l’espace est consommée (à juste raison) par les données représentées.
Analyse dans JavaScript Nécessite une implémentation DOM XML et du code d’application supplémentaire pour mapper le texte dans des objets JavaScript. Aucun code d’application supplémentaire n’est nécessaire pour analyser le texte ; peut utiliser la fonction eval de JavaScript.
Courbe d’apprentissage En règle générale, il a tendance à exiger l’utilisation de plusieurs technologies de concert : XPath, schéma XML, XSLT, espaces de noms XML, DOM, etc. Pile de technologies très simple qui est déjà familière aux développeurs ayant une expérience en JavaScript ou d’autres langages de programmation dynamique.

JSON est un format d’échange de données relativement nouveau qui n’a pas les années d’adoption ou de prise en charge du fournisseur dont BÉNÉFICIE AUJOURD’hui XML (bien que JSON rattrape rapidement). Le tableau suivant met en évidence l’état actuel des affaires dans les espaces XML et JSON.

Différences de prise en charge entre XML et JSON

Support XML JSON
Outils Bénéficie d’un ensemble mature d’outils largement disponibles auprès de nombreux fournisseurs du secteur. La prise en charge des outils riches, tels que les éditeurs et les formateurs, est rare.
Microsoft .NET Framework Prise en charge très bonne et mature depuis la version 1.0 du .NET Framework. La prise en charge xml est disponible dans le cadre de la bibliothèque de classes de base (BCL). Pour les environnements non managés, il existe MSXML. Aucun jusqu’à présent, à l’exception d’une implémentation initiale dans le cadre de ASP.NET AJAX.
Plateforme et langage Les analyseurs et les formateurs sont largement disponibles sur de nombreuses plateformes et langages (implémentations commerciales et open source). Les analyseurs et les formateurs sont déjà disponibles sur de nombreuses plateformes et dans de nombreuses langues. Consultez json.org pour obtenir un bon ensemble de références. Pour l’instant, la plupart des implémentations ont tendance à être open source projets.
Langage intégré Les fournisseurs du secteur expérimentent actuellement une prise en charge littérale dans les langues. Pour plus d’informations, consultez le projet LINQ de Microsoft . Est pris en charge en mode natif dans JavaScript/ECMAScript uniquement.

Note Aucune table n’est censée être une liste complète de points de comparaison. Il existe d’autres angles sur lesquels les deux formats de données peuvent être comparés, mais nous avons estimé que ces points clés devraient être suffisants pour créer une impression initiale.

Création et analyse de messages JSON avec JavaScript

Lorsque vous utilisez JSON comme format d’échange de données, deux tâches courantes transforment une représentation native et en mémoire en sa représentation texte JSON et vice versa. Malheureusement, au moment de l’écriture, JavaScript ne fournit pas de fonctions intégrées pour créer du texte JSON à partir d’un objet ou d’un tableau donné. Ces méthodes devraient être incluses dans la quatrième édition de la norme ECMAScript en 2007. Jusqu’à ce que ces fonctions de mise en forme JSON soient officiellement ajoutées à JavaScript et largement disponibles dans les implémentations populaires, utilisez le script d’implémentation de référence disponible en téléchargement à l’adresse http://www.json.org/json.js.

Dans sa dernière itération au moment de la rédaction de cet article, le script json.js à www.json.org ajoute des fonctions toJSONString() aux types array, string, Boolean, object et autres JavaScript. Les fonctions toJSONString() pour les types scalaires (comme Number et Boolean) sont assez simples, car elles doivent uniquement retourner une représentation sous forme de chaîne de la valeur instance. La fonction toJSONString() pour le type booléen , par exemple, retourne la chaîne « true » si la valeur est true, et « false » dans le cas contraire. Les fonctions toJSONString() pour les types Array et Object sont plus intéressantes. Pour les instances array, la fonction toJSONString() de chaque élément contenu est appelée en séquence, les résultats étant concaténés avec des virgules pour délimiter chaque résultat. Sortie finale entre crochets. De même, pour les instances d’objet, chaque membre est énuméré et sa fonction toJSONString() appelée. Le nom du membre et la représentation JSON de sa valeur sont concaténés avec un signe deux-points au milieu ; chaque paire de nom de membre et de valeur est délimitée par une virgule et la sortie entière est placée entre crochets.

Le résultat net des fonctions toJSONString() est que n’importe quel type peut être converti dans son format JSON avec un seul appel de fonction. Le Code JavaScript suivant crée un objet Array et ajoute 7 éléments String délibérément à l’aide de la méthode détaillée et non littérale à des fins d’illustration. Il affiche ensuite la représentation JSON des tableaux :

  
    // josn.js must be included prior to this point

var continents = new Array();
continents.push("Europe");
continents.push("Asia");
continents.push("Australia");
continents.push("Antarctica");
continents.push("North America");
continents.push("South America");
continents.push("Africa");

alert("The JSON representation of the continents array is: " +
 continents.toJSONString());
  

Bb299886.intro_to_json01(en-us,MSDN.10).gif

Figure 1. La fonction toJSONString() émet le tableau mis en forme selon la norme JSON.

L’analyse du texte JSON est encore plus simple. Étant donné que JSON n’est qu’un sous-ensemble de littéraux JavaScript, il peut être analysé dans une représentation en mémoire à l’aide de la fonction , eval(expr)qui traite le texte JSON source comme du code source JavaScript. La fonction d’évaluation accepte comme entrée une chaîne de code JavaScript valide et évalue l’expression. Par conséquent, la seule ligne de code suivante est tout ce qui est nécessaire pour transformer du texte JSON en une représentation native :

  
    var value = eval( "(" + jsonText + ")" );
  

Note Les parenthèses supplémentaires sont utilisées pour que eval traite inconditionnellement l’entrée source comme une expression. Ceci est particulièrement important pour les objets. Si vous essayez d’appeler eval avec une chaîne contenant du texte JSON qui définit un objet, comme la chaîne «{} » (c’est-à-dire un objet vide), elle retourne simplement undefined comme résultat analysé. Les parenthèses forcent l’analyseur JavaScript à voir les accolades de niveau supérieur comme notation littérale d’un object instance plutôt que, par exemple, des accolades définissant un bloc d’instructions. Incidemment, le même problème ne se produit pas si l’élément de niveau supérieur est un tableau, comme dans eval(« [1,2,3] »). Toutefois, par souci d’uniformité, le texte JSON doit toujours être entouré de parenthèses avant d’appeler l’évaluation afin qu’il n’y ait aucune ambiguïté sur la façon d’interpréter la source.

Lors de l’évaluation de la notation littérale, une instance correspondant à la syntaxe littérale est retournée et affectée à value. Prenons l’exemple suivant, qui utilise la fonction eval pour analyser la notation littérale d’un tableau et affecter le tableau obtenu aux continents variables.

  
    var arrayAsJSONText = '["Europe", "Asia", "Australia", "Antarctica",
 "North America", "South America", "Africa"]';
var continents = eval( arrayAsJSONText );
alert(continents[0] + " is one of the " + continents.length + "
 continents.");
  

Bien sûr, dans la pratique, le texte JSON évalué provient d’une source externe plutôt que d’être codé en dur comme dans le cas ci-dessus.

La fonction d’évaluation évalue aveuglément toute expression passée. Une source non fiable peut donc inclure du Code JavaScript potentiellement dangereux avec ou mélangé dans la notation littérale qui compose les données JSON. Dans les scénarios où la source ne peut pas être approuvée, il est vivement recommandé d’analyser le texte JSON à l’aide de la fonction parseJSON() (disponible dans json.js) :

  
    // Requires json.js
var continents = arrayAsJSONText.parseJSON();
  

La fonction parseJSON() utilise également eval, mais uniquement si la chaîne contenue dans arrayAsJSONText est conforme à la norme de texte JSON. Pour ce faire, il utilise un test d’expression régulière intelligent.

Utilisation de JSON dans le .NET Framework

Le texte JSON peut facilement être créé et analysé à partir de code JavaScript, ce qui fait partie de son attrait. Toutefois, lorsque JSON est utilisé dans une application web ASP.NET, seul le navigateur bénéficie de la prise en charge de JavaScript, car le code côté serveur est probablement écrit en Visual Basic ou C#.

La plupart des bibliothèques Ajax conçues pour ASP.NET prennent en charge la création et l’analyse par programmation de texte JSON. Par conséquent, pour utiliser JSON dans une application .NET, envisagez d’utiliser l’une de ces bibliothèques. Il existe de nombreuses options open source et tierces, et Microsoft dispose également de sa propre bibliothèque Ajax nommée ASP.NET AJAX.

Dans cet article, nous allons examiner des exemples qui utilisent Jayrock, une implémentation open source de JSON pour Microsoft .NET Framework créée par le co-auteur Atif Aziz. Nous avons choisi d’utiliser Jayrock au lieu de ASP.NET AJAX pour trois raisons :

  • Jayrock est open source, ce qui permet d’étendre ou de personnaliser en fonction des besoins.
  • Jayrock peut être utilisé dans les applications ASP.NET 1.x, 2.0 et Mono , tandis que ASP.NET AJAX est destiné à ASP.NET version 2.0 uniquement.
  • L’étendue de Jayrock est limitée à JSON et JSON-RPC, et la première est le main objectif de cet article. Bien que ASP.NET AJAX offre une certaine prise en charge de la création et de l’analyse de texte JSON, son objectif principal est d’offrir une plateforme riche pour la création d’applications web de type Ajax de bout en bout dans ASP.NET. Les cloches et les sifflets supplémentaires peuvent être distrayants lorsque votre main focus est JSON.

L’utilisation de JSON dans .NET à l’aide de Jayrock est similaire à l’utilisation de XML via les classes XmlWriter, XmlReader et XmlSerializer dans le .NET Framework. Les classes JsonWriter, JsonReader, JsonTextWriter et JsonTextReader trouvées dans Jayrock imitent la sémantique des classes .NET Framework XmlWriter, XmlReader, XmlTextWriter et XmlTextReader. Ces classes sont utiles pour l’interfaçage avec JSON à un niveau bas et orienté flux. À l’aide de ces classes, du texte JSON peut être créé ou analysé fragmentaire par le biais d’une série d’appels de méthode. Par exemple, à l’aide de la méthode de classe JsonWriterWriteNumber(number) écrit la représentation sous forme de chaîne appropriée du nombre en fonction de la norme JSON. La classe JsonConvert propose des méthodes Export et Import pour la conversion entre les types .NET et JSON. Ces méthodes fournissent des fonctionnalités similaires à celles trouvées dans les méthodes de classe XmlSerializerSerialize et Déserialize, respectivement.

Création de texte JSON

Le code suivant illustre l’utilisation de la classe JsonTextWriter pour créer le texte JSON pour un tableau de chaînes de continents. Ce texte JSON est envoyé à un TextWriter instance passé dans le constructeur, qui est le flux de sortie de la console dans cet exemple (dans ASP.NET vous pouvez utiliser Response.Output à la place) :

  
    using (JsonTextWriter writer = JsonTextWriter(Console.Out))
{
    writer.WriteStartArray();
    writer.WriteString("Europe");
    writer.WriteString("Asia");
    writer.WriteString("Australia");
    writer.WriteString("Antarctica");
    writer.WriteString("North America");
    writer.WriteString("South America");
    writer.WriteString("Africa");
    writer.WriteEndArray();
}
  

En plus des méthodes WriteStartArray, WriteString et WriteEndArray , la classe JsonWriter fournit des méthodes pour écrire d’autres types de valeurs JSON, tels que WriteNumber, WriteBoolean, WriteNull, etc. Les méthodes WriteStartObject, WriteEndObject et WriteMember créent le texte JSON d’un objet. L’exemple suivant illustre la création du texte JSON pour l’objet contact examiné dans la section « Compréhension de la notation littérale en JavaScript » :

private static void WriteContact()
{
    using (JsonWriter w = new JsonTextWriter(Console.Out))
    {
        w.WriteStartObject();              // {
        w.WriteMember("Name");             //   "Name" : 
        w.WriteString("John Doe");         //     "John Doe",
        w.WriteMember("PermissionToCall"); //   "PermissionToCall" :
        w.WriteBoolean(true);              //     true,
        w.WriteMember("PhoneNumbers");     //   "PhoneNumbers" :
        w.WriteStartArray();               //   [ 
        WritePhoneNumber(w,                //     { "Location": "Home",
            "Home"                         //       "Number": 
            "555-555-1234");               //         "555-555-1234" },
        WritePhoneNumber(w,                //     { "Location": "Work",
            "Work",                        //       "Number": 
            "555-555-9999");               //       "555-555-9999" }
        w.WriteEndArray();                 //   ]
        w.WriteEndObject();                // }
    }
}

private static void WritePhoneNumber(JsonWriter w, string location,
    string number)
{
    w.WriteStartObject();      //  {
    w.WriteMember("Location"); //      "Location" : 
    w.WriteString(location);   //          "...", 
    w.WriteMember("Number");   //      "Number" :
    w.WriteString(number);     //          "..."
    w.WriteEndObject();        //  }
}

Les méthodes Export et ExportToString dans la classe JsonConvert peuvent être utilisées pour sérialiser un type .NET spécifié en texte JSON. Par exemple, au lieu de créer manuellement le texte JSON pour le tableau des sept continents à l’aide de la classe JsonTextWriter , l’appel suivant à JsonConvert.ExportToString produit les mêmes résultats :

string[] continents = {
      "Europe", "Asia", "Australia", "Antarctica", "North America", 
      "South America", "Africa"
};
string jsonText = JsonConvert.ExportToString(continents);

Analyse du texte JSON

La classe JsonTextReader fournit diverses méthodes pour analyser les jetons de texte JSON avec le noyau read. Chaque fois que la méthode Read est appelée, l’analyseur consomme le jeton suivant, qui peut être une valeur de chaîne, une valeur numérique, un nom de membre d’objet, le début d’un tableau, etc. Le cas échéant, le texte analysé du jeton actuel est accessible via la propriété Text . Par exemple, si le lecteur est assis sur des données booléennes, la propriété Text renvoie « true » ou « false » en fonction de la valeur d’analyse réelle.

L’exemple de code suivant utilise la classe JsonTextReader pour analyser la représentation textuelle JSON d’un tableau de chaînes contenant les noms des sept continents. Chaque continent commençant par la lettre « A » est envoyé à la console :

  
    string jsonText = @"[""Europe"", ""Asia"", ""Australia"", ""Antarctica"",
 ""North America"", ""South America"", ""Africa""]";

using (JsonTextReader reader = new JsonTextReader(new
 StringReader(jsonText)))
{
    while (reader.Read())
    {
        if (reader.TokenClass == JsonTokenClass.String &&
            reader.Text.StartsWith("A"))
        {
            Console.WriteLine(reader.Text);
        }
    }
}
  

Note La classe JsonTextReader dans Jayrock est un analyseur de texte JSON assez libéral. Il autorise en fait beaucoup plus de syntaxe que n’est considéré comme un texte JSON valide selon les règles énoncées dans RFC 4627. Par exemple, la classe JsonTextReader permet aux commentaires sur une seule ligne et sur plusieurs lignes d’apparaître dans du texte JSON comme prévu dans JavaScript. Les commentaires d’une seule ligne commencent par une barre oblique (//) et les commentaires multilignes par une barre oblique star (/*) et se terminent par star-barre oblique (*/). Les commentaires sur une seule ligne peuvent même commencer par le signe hachage/dièse (#), qui est courant dans les fichiers de configuration de style Unix. Dans tous les cas, les commentaires sont complètement ignorés par l’analyseur et ne sont jamais exposés via l’API. De même que dans JavaScript, JsonTextReader permet à une chaîne JSON d’être délimitée par une apostrophe ('). L’analyseur peut même tolérer une virgule supplémentaire après le dernier membre d’un objet ou d’un élément d’un tableau.

Même avec tous ces ajouts, JsonTextReader est un analyseur conforme ! JsonTextWriter, en revanche, produit uniquement du texte JSON strictement conforme aux normes. Ceci suit ce qui est souvent inventé comme le principe de robustesse, qui dit: « Soyez conservateur dans ce que vous faites; être libéral dans ce que vous acceptez des autres.

Pour convertir du texte JSON directement en objet .NET, utilisez la méthode d’importation de la classe JsonConvert , en spécifiant le type de sortie et le texte JSON. L’exemple suivant montre la conversion d’un tableau JSON de chaînes en tableau de chaînes .NET :

string jsonText = @"[""Europe"", ""Asia"", ""Australia"", ""Antarctica"",
 ""North America"", ""South America"", ""Africa""]";

string[] continents = (string[]) JsonConvert.Import(typeof(string[]),
 jsonText);

Voici un exemple plus intéressant de conversion qui prend un flux XML RSS, le désérialise en un type .NET à l’aide de XmlSerializer, puis convertit l’objet en texte JSON à l’aide de JsonConvert (conversion effective de RSS dans XML en texte JSON) :

XmlSerializer serializer = new XmlSerializer(typeof(RichSiteSummary));
RichSiteSummary news;

// Get the MSDN RSS feed and deserialize it...

using (XmlReader reader = XmlReader.Create("https://msdn.microsoft.com/rss.xml"))
    news = (RichSiteSummary) serializer.Deserialize(reader);

// Export the RichSiteSummary object as JSON text, emitting the output to
// Console.Out.

using (JsonTextWriter writer = new JsonTextWriter(Console.Out))
    JsonConvert.Export(news, writer);

Note Vous trouverez la définition de RichSiteSummary et ses types associés dans les exemples qui accompagnent cet article.

Utilisation de JSON dans ASP.NET

Après avoir examiné les façons d’utiliser JSON en JavaScript et à partir du .NET Framework à l’aide de Jayrock, il est temps de se tourner vers un exemple pratique montrant où et comment toutes ces connaissances peuvent être appliquées. Prenons l’exemple de la fonctionnalité de rappel de script client dans ASP.NET 2.0, qui simplifie le processus d’appels hors bande à partir du navigateur web vers la page ASP.NET (ou vers un contrôle particulier de la page). Dans un scénario de rappel classique, le script côté client dans le navigateur empaquette et renvoie les données au serveur web pour un traitement par une méthode côté serveur. Après avoir reçu les données de réponse du serveur, le client les utilise pour mettre à jour l’affichage du navigateur.

Note Pour plus d’informations, consultez l’article Rappels de script du magazine MSDN dans ASP.NET 2.0.

Le problème dans un scénario de rappel de client est que le client et le serveur ne peuvent envoyer qu’une chaîne d’aller-retour. Par conséquent, les informations à échanger doivent être converties d’une représentation native en mémoire en chaîne avant d’être envoyées, puis analysées à partir d’une chaîne vers sa représentation native en mémoire lorsqu’elles sont reçues. La fonctionnalité de rappel de script client dans ASP.NET 2.0 ne nécessite pas de format de chaîne particulier pour les données échangées, et ne fournit pas non plus de fonctionnalités intégrées pour la conversion entre les représentations natives en mémoire et sous forme de chaîne ; il appartient au développeur d’implémenter la logique de conversion en fonction d’un format d’échange de données de son choix.

L’exemple suivant montre comment utiliser JSON comme format d’échange de données dans un scénario de rappel de script client. En particulier, l’exemple se compose d’une page ASP.NET qui utilise les données de la base de données Northwind pour fournir une liste déroulante des catégories ; les produits de la catégorie sélectionnée sont affichés dans une liste à puces (voir la figure 3). Chaque fois que la liste déroulante est modifiée côté client, un rappel est effectué en passant dans un tableau dont l’élément unique est le CategoryID sélectionné.

Note Nous transmettons un tableau qui contient le CategoryID sélectionné comme seul élément (plutôt que simplement l’ID de catégorie), car la norme JSON exige que tout texte JSON ait un objet ou un tableau comme racine. Bien entendu, le client n’est pas obligé de passer du texte JSON au serveur. Cet exemple aurait pu passer uniquement le CategoryID sélectionné sous forme de chaîne. Toutefois, nous voulions illustrer l’envoi de texte JSON dans les messages de demande et de réponse du rappel.

Le code suivant dans le gestionnaire d’événements Page_Load configure le contrôle Web Categories DropDownList de sorte que lorsqu’il est modifié, la fonction GetProductsForCategory est appelée et a passé la valeur des listes déroulantes sélectionnée. Cette fonction lance le rappel de script client si la valeur de liste déroulante passée est supérieure à zéro :

  
    // Add client-side onchange event to drop-down list
Categories.Attributes["onchange"] = "Categories_onchange(this);";

// Generate the callback script
string callbackScript = ClientScript.GetCallbackEventReference(
    /* control        */ this, 
    /* argument       */ "'[' + categoryID + ']'", 
    /* clientCallback */ "showProducts", 
    /* context        */ "null");

// Add the Categories_onchange function
ClientScript.RegisterClientScriptBlock(GetType(),
"Categories_onchange", @"
    function Categories_onchange(sender)
    {
        clearResults();

        var categoryID = sender.value;            
        if (categoryID > 0)
        {
            " + callbackScript + @"
        }
    }", true);
  

La méthode GetCallBackEventReference dans la classe ClientScriptManager , qui est utilisée pour générer le code JavaScript qui appelle le rappel, a la signature suivante :

  
    public string GetCallbackEventReference (
    Control control,
    string argument,
    string clientCallback,
    string context,
)
  

Le paramètre argument spécifie les données envoyées du client au serveur web pendant le rappel, et le paramètre clientCallback spécifie le nom de la fonction côté client à appeler à l’achèvement du rappel (showProducts). L’appel de méthode GetCallBackEventReference génère le code JavaScript suivant et l’ajoute au balisage rendu :

  
    WebForm_DoCallback('__Page','[' + categoryID + 
']',showProducts,null,null,false)
  

'[' + categoryID + ']' est la valeur qui est passée au serveur pendant le rappel (un tableau avec un élément unique, categoryID) et showProducts est la fonction JavaScript qui est exécutée lorsque le rappel est retourné.

Côté serveur, la méthode exécutée en réponse au rappel utilise la classe JsonConvert de Jayrock pour analyser le texte JSON entrant et mettre en forme le texte JSON sortant. En particulier, les noms des produits associés à la catégorie sélectionnée sont récupérés et retournés sous forme de tableau de chaînes.

  
    // Deserialize the JSON text into an array of integers
int[] args = (int[]) JsonConvert.Import(typeof(int[]), eventArgument);

// Read the selected CategoryID from the array
int categoryID = args[0];

// Get products based on categoryID 

  NorthwindDataSet.ProductsRow[] rows = 
Northwind.Categories.FindByCategoryID(categoryID).GetProductsRows();

// Load the names into a string array
string[] productNames = new string[rows.Length];
for (int i = 0; i < rows.Length; i++)
{
    productNames[i] = rows[i].ProductName;
}

// Serialize the string array as JSON text and return it to the client
return JsonConvert.ExportToString(productNames);

Note La classe JsonConvert est utilisée deux fois, une fois pour convertir le texte JSON dans eventArgument en tableau d’entiers, puis pour convertir le tableau de chaînes productNames en texte JSON à retourner au client. Nous aurions également pu utiliser les classes JsonReader et JsonWriter ici, mais JsonConvert effectue le même travail assez bien lorsque les données impliquées sont relativement petites et facilement mappées à des types existants.

Lorsque les données sont retournées côté serveur, la fonction JavaScript spécifiée à partir de la méthode GetCallBackEventReference est appelée et a passé la valeur de retour. Cette méthode JavaScript, showProducts, commence par référencer l’élément <div>ProductOutput. Il analyse ensuite la réponse JSON et ajoute dynamiquement une liste non triée avec un élément de liste pour chaque élément de tableau. Si aucun produit n’est retourné pour la catégorie sélectionnée, un message correspondant s’affiche à la place.

function showProducts(arg, context)
{
    // Dump the JSON text response from the server.

    document.forms[0].JSONResponse.value = arg;
    
    // Parse JSON text returned from callback.

    var categoryProducts = eval("(" + arg + ")");

    // Get a reference to the <div> ProductOutput.
    
    var output = document.getElementById("ProductOutput");

    // If no products for category, show message.
    
    if (categoryProducts.length == 0)
    {
        output.appendChild(document.createTextNode(
            "There are no products for this category..."));
    }
    else
    {
        // There are products, display them in an unordered list. 
        
        var ul = document.createElement("ul");
        
        for (var i = 0; i < categoryProducts.length; i++)
        {
            var product = categoryProducts[i];
            var li = document.createElement("li");
            li.appendChild(document.createTextNode(product));
            ul.appendChild(li);
        }
        
        output.appendChild(ul);
    }
}

La figure 2 illustre la séquence d’événements tandis que la figure 3 montre cet exemple en action ; Le code complet est inclus dans ce téléchargement d’articles.

Bb299886.intro_to_json02(en-us,MSDN.10).gif

Figure 2 : Le client envoie le CategoryID sélectionné en tant qu’élément unique dans un tableau et le serveur retourne un tableau de noms de produits associés.

Bb299886.intro_to_json03(en-us,MSDN.10).gif

Figure 3 : Les produits sont affichés dans une liste à puces à l’intérieur de la catégorie sélectionnée.

Conclusion

JSON est un format léger d’échange de données textuel basé sur un sous-ensemble de la notation littérale du langage de programmation JavaScript. Il fournit un encodage succinct pour les structures de données d’application et est généralement utilisé dans les scénarios où une implémentation JavaScript est disponible pour l’une ou les deux applications qui échangent des données, comme dans les applications web de style Ajax. L’attrait de JSON réside dans sa simplicité de compréhension, d’adoption et d’implémentation. JSON n’a pratiquement aucune courbe d’apprentissage pour les développeurs déjà familiarisés avec JavaScript ou d’autres langages de programmation avec une prise en charge similaire d’une notation littérale riche (comme Python et Ruby). L’analyse du texte JSON dans du code JavaScript peut être effectuée en appelant simplement la fonction d’évaluation , et la création de texte JSON est un jeu d’enfant avec le script json.js fourni à l’adresse http://www.json.org/json.js.

Il existe un nombre important de bibliothèques permettant d’utiliser JSON sur toutes les principales plateformes et infrastructures. Dans cet article, nous avons examiné Jayrock, une bibliothèque open source permettant de créer et d’analyser du texte JSON dans des applications .NET. Jayrock peut être utilisé dans ASP.NET applications 1.x, 2.0 et Mono. ASP.NET AJAX offre des fonctionnalités JSON similaires, mais pour les applications ASP.NET 2.0 uniquement.

Bonne programmation!

Références

Ajax ou AJAX ?

Le terme Ajax a été initialement inventé par Jesse James Garrett pour décrire le style des applications web et l’ensemble de technologies impliquées dans la création d’applications web hautement interactives. Historiquement, le terme Ajax s’est répandu sur le web sous la forme de l’acronyme AJAX, ce qui signifie JavaScript asynchrone et XML. Toutefois, avec le temps, les utilisateurs se sont rendu compte que le « X » dans AJAX n’était pas très représentatif du format de données sous-jacent utilisé pour communiquer avec le serveur web en arrière-plan, car la plupart des implémentations passaient vers JSON comme alternative plus simple et plus efficace. Donc, plutôt que de trouver un acronyme de remplacement comme AJAJ qui est un peu de langue-twister, l’acronyme est généralement retiré en faveur d’Ajax le terme plutôt que AJAX l’acronyme.

Au moment de la rédaction de cet article, attendez-vous à voir une utilisation mixte et large de « AJAX » et « Ajax » pour signifier une seule et même chose. Dans cet article, nous avons bloqué avec « Ajax le terme ». Toutefois, les produits commerciaux qui fournissent des frameworks permettant des applications de style Ajax ont tendance à utiliser la forme de l’acronyme pour se distinguer d’un produit d’agent de nettoyage nommé de même nom et pour éviter tout litige potentiel en matière de marque ou de droit.

ASP.NET AJAX : chaîne de date et d’heure JSON à l’intérieur

Le sérialiseur JSON AJAX dans ASP.NET encode un instance DateTime sous forme de chaîne JSON. Au cours de ses cycles de préversion, ASP.NET AJAX a utilisé le format « @ticks@ », où les graduations représentent le nombre de millisecondes depuis le 1er janvier 1970 en temps universel coordonné (UTC). Une date et une heure UTC telles que le 29 novembre 1989 à 04:55:30 seraient écrites comme « @62831853071@ ». Bien que simple et direct, ce format ne peut pas faire la différence entre une valeur de date et d’heure sérialisée et une chaîne qui ressemble à une date sérialisée, mais qui n’est pas destinée à être désérialisée en tant qu’une seule. Par conséquent, l’équipe ajax ASP.NET a apporté une modification à la version finale pour résoudre ce problème en adoptant le format « \/Date(ticks)\/ ».

Le nouveau format s’appuie sur une petite astuce pour réduire le risque de mauvaise interprétation. Dans JSON, un caractère de barre oblique (/) dans une chaîne peut être placé dans une séquence d’échappement avec une barre oblique inverse (\), même s’il n’est pas strictement requis. En tirant parti de cela, l’équipe ASP.NET AJAX a modifié JavaScriptSerializer pour écrire un instance DateTime sous la forme de la chaîne « \/Date(ticks)\/ ». L’échappement des deux barres obliques est superficiel, mais significatif pour JavaScriptSerializer. Par des règles JSON, "\/Date(ticks)\/" est techniquement équivalent à "/Date(ticks)/" mais le JavaScriptSerializer désérialise le premier en tant que DateTime et le second en tant que Chaîne. Les risques d’ambiguïté sont donc considérablement moindres par rapport au format « @ticks@ » plus simple des préversions.

Remerciements spéciaux

Avant de soumettre cet article à MSDN, un certain nombre de bénévoles nous ont aidé à relire l’article et à fournir des commentaires sur le contenu, la grammaire et l’orientation. Les principaux contributeurs au processus d’examen sont Douglas Crockford, Eric Schönholzer et Milan Negovan.

À propos des auteurs

Atif Aziz est consultant principal chez Skybow AG, où son objectif principal est d’aider les clients à comprendre et à créer des solutions sur la plateforme de développement .NET. Atif contribue régulièrement à la communauté des développeurs Microsoft en prenant la parole lors de conférences et en écrivant des articles pour des publications techniques. Il est conférencier ineta et président du plus grand groupe d’utilisateurs .NET suisse. Il est accessible à l’adresse atif.aziz@skybow.com ou via son site web à l’adresse http://www.raboof.com.

Scott Mitchell, auteur de six livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies web Microsoft depuis 1998. Scott travaille comme consultant indépendant, formateur et écrivain. Il est accessible à l’adresse mitchell@4guysfromrolla.com ou via son blog : http://ScottOnWriting.net.