begin process at 2010 02 10 00:12:45
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

ASP.Net

 > OPTIMISATION DE LA SERIALISATION JSON POUR LES LIST<T>

OPTIMISATION DE LA SERIALISATION JSON POUR LES LIST<T>


 Information sur la source

Note :
Aucune note
Catégorie :ASP.Net Source .NET ( DotNet ) Classé sous :json, serialisation, WCF, Service web, linq Niveau :Initié Date de création :26/05/2008 Date de mise à jour :26/05/2008 11:17:30 Vu / téléchargé :7 355 / 88

Auteur : jesusonline

Ecrire un message privé
Site perso
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (0)
Ajouter un commentaire et/ou une note


 Description

Cette source permet d'optimiser la sérialisation JSON d'une List<T>. Par défaut si un WebService retourne une List<T> alors toutes les propriétés seront répétés pour chacun des objets.
On obtient alors un JSON ressemblant à :

{"d": [
   {
      "__type":"Person:#",
      "BirthDate":"\/Date(1211790363564+0200)\/",
      "City":"Chénas",
      "FirstName":"Steven",
      "LastName":"Vincent"
   },{
      "__type":"Person:#",
      "BirthDate":"\/Date(1211790441107+0200)\/",
      "City":"Légny",
      "FirstName":"Janet",
      "LastName":"laurent"
   },{
   // etc...

Cette astuce permet d'avoir un json ressemblant à :

{"d":{
   "Columns":[
      "FirstName",
      "LastName",
      "BirthDate",
      "City"
   ],"Values":[
      ["Andrew","Alex","\/Date(1211790586937+0200)\/","S aint-Didier-sur-Beaujeu"],
      ["Laura","Claude","\/Date(1211790697591+0200)\/"," Chénas"],
      ["Anne","Isabelle","\/Date(1211790655756+0200)\/", "Saint-Cyr-le-Chatoux"],
      ["Nancy","Steph","\/Date(1211790592372+0200)\/","S ainte-Paule"],
// etc

On obtient un gain de traffic de l'ordre de 50%.

Source

  • using System;
  • using System.Data;
  • using System.Configuration;
  • using System.Linq;
  • using System.Web;
  • using System.Web.Security;
  • using System.Web.UI;
  • using System.Web.UI.HtmlControls;
  • using System.Web.UI.WebControls;
  • using System.Web.UI.WebControls.WebParts;
  • using System.Xml.Linq;
  • using System.Runtime.Serialization;
  • using System.Collections.Generic;
  • using System.Reflection;
  • /// <summary>
  • /// Permet d'optimiser la serailisation JSON d'une List&lt;T&gt;
  • /// </summary>
  • /// <typeparam name="T"></typeparam>
  • [DataContract]
  • public class JsonList<T>
  • {
  • #region Constructors
  • private static IEnumerable<String> _columns;
  • private static IEnumerable<PropertyInfo> _properties;
  • /// <summary>
  • /// Ce constructeur sera appelé lors de la premiere utilisation du type "finale" => pour chaque T
  • /// </summary>
  • static JsonList()
  • {
  • // mis en cache de la liste des colonne en fonction du type T
  • // TODO : Je ne prend pas en compte toutes les options du DataMemberAttribute, il y a donc des bugs si on joue avec des cas spécifique
  • _properties = (from property in typeof(T).GetProperties()
  • let dataMemberAttributes = (DataMemberAttribute[])property.GetCustomAttributes(typeof(DataMemberAttribute), false)
  • where dataMemberAttributes.Length > 0
  • select property
  • ).ToList(); // ToList pour pas garder le IEnumerable et donc refaire la requête à chaque fois
  • _columns = (from property in _properties
  • // on pourrait mettre la recherche de l'attribut en cache à partir de la requete précedente,
  • // mais cela nécessite de créer une structure rien que pour ca ...
  • let dataMemberAttribute = ((DataMemberAttribute[])property.GetCustomAttributes(typeof(DataMemberAttribute), false))[0]
  • select !String.IsNullOrEmpty(dataMemberAttribute.Name) ? dataMemberAttribute.Name : property.Name
  • ).ToList(); // ToList pour pas garder le IEnumerable et donc refaire la requête à chaque fois
  • }
  • private IEnumerable<T> _innerList;
  • public JsonList(IEnumerable<T> innerList)
  • {
  • this._innerList = innerList;
  • }
  • #endregion
  • #region implicit casting operator
  • public static implicit operator JsonList<T>(List<T> items)
  • {
  • return new JsonList<T>(items);
  • }
  • public static implicit operator JsonList<T>(T[] items)
  • {
  • return new JsonList<T>(items);
  • }
  • #endregion
  • #region Properties
  • /// <summary>
  • /// Contient un tableau contenant le nom des différents colonnes
  • /// </summary>
  • [DataMember]
  • public IEnumerable<String> Columns
  • {
  • get { return _columns; }
  • set { throw new NotSupportedException("Deserialization of this object is not supporter yet"); }
  • }
  • /// <summary>
  • /// Contient un tableau de tableau contenant les valeurs de la list
  • /// </summary>
  • /// <remarks>
  • /// [
  • /// ['FirstName1', 'LastName1'],
  • /// ['FirstName2', 'LastName2']
  • /// ]
  • /// </remarks>
  • [DataMember]
  • public IEnumerable<IEnumerable<Object>> Values
  • {
  • get
  • {
  • // TODO : optimiser ca en utilisant les Expression de C#3 afin de mettre en cache le getter
  • return from item in this._innerList
  • select from property in _properties
  • select property.GetValue(item, null);
  • }
  • set { throw new NotSupportedException("Deserialization of this object is not supporter yet"); }
  • }
  • #endregion
  • }
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Reflection;

/// <summary>
/// Permet d'optimiser la serailisation JSON d'une List&lt;T&gt;
/// </summary>
/// <typeparam name="T"></typeparam>
[DataContract]
public class JsonList<T>
{

    #region Constructors

    private static IEnumerable<String> _columns;
    private static IEnumerable<PropertyInfo> _properties;

    /// <summary>
    /// Ce constructeur sera appelé lors de la premiere utilisation du type "finale" => pour chaque T
    /// </summary>
    static JsonList()
    {
        // mis en cache de la liste des colonne en fonction du type T
        // TODO : Je ne prend pas en compte toutes les options du DataMemberAttribute, il y a donc des bugs si on joue avec des cas spécifique
        _properties = (from property in typeof(T).GetProperties()
                       let dataMemberAttributes = (DataMemberAttribute[])property.GetCustomAttributes(typeof(DataMemberAttribute), false)
                       where dataMemberAttributes.Length > 0
                       select property
                   ).ToList(); // ToList pour pas garder le IEnumerable et donc refaire la requête à chaque fois

        _columns = (from property in _properties
                    // on pourrait mettre la recherche de l'attribut en cache à partir de la requete précedente, 
                    // mais cela nécessite de créer une structure rien que pour ca ...
                    let dataMemberAttribute = ((DataMemberAttribute[])property.GetCustomAttributes(typeof(DataMemberAttribute), false))[0]
                    select !String.IsNullOrEmpty(dataMemberAttribute.Name) ? dataMemberAttribute.Name : property.Name
                   ).ToList(); // ToList pour pas garder le IEnumerable et donc refaire la requête à chaque fois
    }

    private IEnumerable<T> _innerList;

    public JsonList(IEnumerable<T> innerList)
    {
        this._innerList = innerList;
    }

    #endregion

    #region implicit casting operator

    public static implicit operator JsonList<T>(List<T> items)
    {
        return new JsonList<T>(items);
    }
    public static implicit operator JsonList<T>(T[] items)
    {
        return new JsonList<T>(items);
    }

    #endregion

    #region Properties

    /// <summary>
    /// Contient un tableau contenant le nom des différents colonnes
    /// </summary>
    [DataMember]
    public IEnumerable<String> Columns
    {
        get { return _columns; }
        set { throw new NotSupportedException("Deserialization of this object is not supporter yet"); }
    }

    /// <summary>
    /// Contient un tableau de tableau contenant les valeurs de la list 
    /// </summary>
    /// <remarks>
    /// [
    ///   ['FirstName1', 'LastName1'],
    ///   ['FirstName2', 'LastName2']
    /// ]
    /// </remarks>
    [DataMember]
    public IEnumerable<IEnumerable<Object>> Values
    {
        get
        {
            // TODO : optimiser ca en utilisant les Expression de C#3 afin de mettre en cache le getter
            return from item in this._innerList
                   select from property in _properties
                          select property.GetValue(item, null);
        }
        set { throw new NotSupportedException("Deserialization of this object is not supporter yet"); }
    }

    #endregion
}

 Conclusion

L'exemple fourni dans le zip montre la différence entre la serialisation classique et l'optimisation.

J'ai utilisé un service WCF, mais ce code devrait également fonctionner pour les services web asmx classique, il faut juste rajouter un attribut DataMember sur les propriétés à sérializer.

Je ne prend pas en compte toutes les possibilités de l'attribut DataMember de WCF, il se peut qu'il y ait quelques bugs si on n'utilise pas cet attribut comme je l'ai prévu :)

Plus d'explication sont disponible ici : http://blogs.developpeur.org/cyril/archive/2008/05 /26/json-optimiser-serialisation-list-aspnet-ajax. aspx

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

26 mai 2008 11:17:30 :
Rajout d'un lien vers mon post sur mon blog.

 Sources du même auteur

Source .NET (Dotnet) RESPONSE.FILTER : MANIPULATION DU STREAM DE SORTIE ASP.NET
Source avec Zip Source .NET (Dotnet) CRAWLABLELINKBUTTON : UPDATEPANEL ET RÉFÉRENCEMENT
Source .NET (Dotnet) POSTBACKCONTROL - COMMUNICATION CLIENT/SERVEUR AVEC LES UPDA...
Source avec Zip Source .NET (Dotnet) COMPACTER DU JAVASCRIPT
Source avec Zip Source .NET (Dotnet) LINQ : BINDER UN TREEVIEW AVEC UN IENUMERABLE : L'EXTENSION ...

 Sources de la même categorie

Source avec Zip Source .NET (Dotnet) CUSTOM DATEPIKER DÉRIVANT DE COMPOSITECONTROL par fredzool
Source avec Zip UN MODULE POUR APPRENDRE SQL par Elmarzougui
Source avec Zip Source .NET (Dotnet) BOUTON QUI EMPECHE LE MULTI CLIC AVANT LA FIN DU TRAITEMENT.... par fredzool
Source avec Zip Source .NET (Dotnet) BOUTON AVEC CSS ET USERCONTROL WITH EVENT par fredzool
Source avec Zip Source .NET (Dotnet) CAPTCHA ASP.NET ET JAVASCRIPT par vaan3713

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture Source .NET (Dotnet) GRIDVIEW UTILISANT LINQ ET REFLECTION par jmenfous
Source avec Zip Source avec une capture Source .NET (Dotnet) EXTENDER GRIDVIEW POUR TRAITEMENTS LOURDS DE LISTES par Yxion
Source .NET (Dotnet) POSTBACKCONTROL - COMMUNICATION CLIENT/SERVEUR AVEC LES UPDA... par jesusonline
Source avec Zip Source .NET (Dotnet) LINQ : BINDER UN TREEVIEW AVEC UN IENUMERABLE : L'EXTENSION ... par jesusonline

Commentaires et avis

Aucun commentaire pour le moment.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Gridview - Linq - Mode édition et DropDownList [ par tvaillie ] Bonjour.J'ai un souci alors que j'essaie d'utiliser une gridview avec du Linq. (Je ne suis pas sur que le problème vienne de Linq d'ailleurs)Je vous e Probleme avec le WCF service Host de visual studio 2008 [ par juju008 ] Bonjour à tous, Je suis depuis plus de 24h consécutives à la recherche d'une solution à mon probleme. J'ai créé nouveau projet de workflow séquentiel question Linq to sql [ par ChamY ] Bonjour,Je bloque sur un truc surement bête et je recherche de l'aide surr du Linq To Sql.Donc j'ai une page avec un gridview qui liste mes taches et Silverlight et WCF [ par mastoc ] Bonjour !bon tout d'abord je pose ma question ici car ce forum me semble le plus approprié. J'espère que c'est cas sinon veuillez m'excuser d'avance:) linq - jointure de table [ par wally88 ] Bonjour,  je n'arrive pas a joindre mes tables ou a "trier" :'(exemple pour récupérer les lignes en rapport entre deux tables, je lui dis que la table Erreur WCF : Le ChannelDispatcher ne peut pas ouvrir son IChannelListener [ par EmacLi ] Bonjour,Je viens de créer un service WCF mais pas moyen de le faire démarrer par mon application hote (application console). Il me retourne l'erreur s Problème ItemDataBound, DataItem avec LINQ [ par walterskinner ] Bonjour, Cela fait maintenant deux jours que je cherche erreur due à InsertAllOnSubmit() [ par khawlaaa ] Bonjour tout le monde , je suis entrain de travailler sur un WebSite ( asp.net et C#) j'ai divisé mon projet en 3 couches: *UI *BLL *DAO L WCF -- WEB CONFIG -- DMZ [ par Kikuts ] Bonjour, j'ai une application silverlight qui utilise un web service. En local tout marche toujours ! Sur un serveur, ça marche en trichant un peu. Su


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,842 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales