- JSON désérialisation avec JSON.net: hiérarchies de classes - Licence Fondamentale d'Informatique
mardi 27 août 2013

JSON désérialisation avec JSON.net: hiérarchies de classes

Dans la partie 1 de cette série que j'ai décrit les bases de la création de classes à partir d'une chaîne JSON et puis tout simplement désérialisant la chaîne dans un (Liste des) cours. De cette façon, vous n'avez pas toutes les hooplah de SOAP, mais qui ont encore des classes fortement typées dans votre application client. Mais méfiez-vous, il n'ya pas de contrat formel soit, si un beau matin vous pourriez commencer à penser que, soit vous avez eu trop de boisson hier soir, ou que l'entreprise qui fournit le flux de données de votre application en effet a commencé à vendre des Windows Phone 7 appareils fabriqués par Sony, avec un "écran 65.
En regardant la chaîne JSON vous voyez maintenant quelque chose comme ceci:

[
  {
    "Marque": "Nokia", "Type": "Lumia 800", "périphériques": "Téléphone",
    "Specs": {"stockage": "16 Go", "Memory": "512", "l'Ecran": "3,7"}
  },
  {
    "Marque": "Sony", "Type": "KDL-65HX920", "périphériques": "TV",
    "Specs": {"Screensize": "65", "FullHD": "Oui", "ThreeD": "Oui"}
  },  
  {"Marque": "Nokia", "Type": "Lumia 900", "périphériques": "Téléphone",
    "Specs": {"stockage": "8 Go", "Memory": "512", "l'Ecran": "4,3"}
  },
  {
    "Marque": "Samsung", "Type": "UE55C9000", "périphériques": "TV",
    "Specs": {"Screensize": "55", "FullHD": "Oui", "ThreeD": "Oui"}
  },  
]

Aucune des deux options mentionnées avant de comparaître pour être vrai: apparemment, la société s'est diversifiée.Ils vendent maintenant des téléviseurs ainsi. Bien sûr, vous pouvez exécuter ce creux json2csharp , qui vous donnera ceci:

Spécifications public class
{
    Stockage public string {get; fixer;}
    Mémoire public string {get; fixer;}
    Screensize public string {get; fixer;}
    public string FullHD {get; fixer;}
    ThreeD public string {get; fixer;}
}

public class RootObject
{
    Marque chaîne publique {get; fixer;}
    Type de public string {get; fixer;}
    Appareil public string {get; mettre;}
    Caractéristiques Caractéristiques publics {get; fixer;}
}

Ce sera travailler, mais pas dans le but de ce que je voudrais montrer. Nous remanier le stuff ensemble dans une structure d'objet comme ceci:


CodeScheme

Or, dans le code (mettre dans un seul fichier pour des raisons de concision)

namespace JsonDemo
{
  Dispositif publique de la classe abstraite
  {
    Marque chaîne publique {get; fixer;}
    Type de public string {get; fixer;}
  }
  
  public class Téléphone: Périphérique
  {
    PhoneSpecs Specs publics {get; fixer;}
  }
  
  Tv public class: Appareil
  {
    TvSpecs Specs publics {get; fixer;}
  }
  
  Spécifications publics de classe abstraite
  {
    Screensize public string {get; fixer;}
  }
  
  PhoneSpecs public class: Spécifications
  {
    Stockage public string {get; fixer;}
    Mémoire public string {get; fixer;}
  }
  
    TvSpecs public class: Spécifications
  {
    public string FullHD {get; fixer;}
    ThreeD public string {get; fixer;}
  }
}

Si vous pensez que c'est une manière compliquée ridicule pour stocker une telle structure de données simple je pense que vous avez tout à fait raison, mais a) ils ne me Un appel ne Architecte Senior Software pour rien, ce qui rend les choses compliquées, c'est ce qu'on me dit architectes font pour une vie, alors j'essaie d'être un bon garçon ;-) et b) c'est juste pour le but de l'échantillon, alors restez avec moi, non?
Si vous vous souvenez l'essentiel de la partie 1: tout cela est arrivé à une seule ligne de code, à savoir:
JsonConvert.DeserializeObject <Liste <Phone>> (r.EventArgs.Result);
Cette méthode a fait un second paramètre: params Newtonsoft.Json.JsonConverter [] convertisseurs , ce qui vous permet de fournir vos propres convertisseurs personnalisés. Est faire ceux assez facile, et il devient encore plus facile lorsque vous utilisez la classe <T> JsonCreationConverter qui est flottant autour de l'Internet dans diverses permutations. J'ai entaillé à partir StackOverflow ici .

using System;
utilisant Newtonsoft.Json;
utilisant Newtonsoft.Json.Linq;

namespace JsonDemo
{
  public abstract class JsonCreationConverter <T>: JsonConverter
  {
    protégé abstrait T Create (Type objectType, JObject JsonObject);

    public override bool CanConvert (Type objectType)
    {
      retourner typeof (T) IsAssignableFrom (objectType).;
    }

    public override objet ReadJson (lecteur JsonReader, Type objectType, 
      objet existingValue, sérialiseur JsonSerializer)
    {
      var = JsonObject JObject.Load (lecteur);
      var target = Create (objectType, JsonObject);
      serializer.Populate (jsonObject.CreateReader (), cible);
      retourner cible;
    }

    du public override void WriteJson (écrivain JsonWriter, la valeur de l'objet, 
   sérialiseur JsonSerializer)
    {
      throw new NotImplementedException ();
    }
  }
}

Pour faire un convertisseur, vous sous-classe de cet objet dans un convertisseur basé sur un modèle pour la classe de base, substituez la méthode "Create" et vous partez. Rédaction d'un convertisseur pour la hiérarchie appareil / téléphone / TV est assez simple: il vous suffit de vérifier la valeur de la propriété "Device", ce que vous faites comme ceci:

using System;
utilisant Newtonsoft.Json.Linq;

namespace JsonDemo
{
  JsonDeviceConverter public class: JsonCreationConverter <Device>
  {
    système de forçage protégé Créer (objectType type, JObject JsonObject)
    {
      var = typeName JsonObject ["Device"] ToString ().;
      switch (typeName)
      {
        cas "TV":
          return new Tv ();
        cas "téléphone":
          return new Téléphone ();
        default: return null;
      }
    }
  }
}

Pour les Specs / PhoneSpecs / TvSpecs vous faire plus ou moins la même, c'est seulement maintenant que vous avez à vérifier pour l' existence de certaines propriétés, et non pas la valeur. J'ai décidé que si un objet a une propriété "Stockage" C'est un PhoneSpecs, et si elle a "FullHD" C'est un TVSpecs.

using System;
utilisant Newtonsoft.Json.Linq;

namespace JsonDemo
{
  JsonSpecsConverter public class: <Specs> de JsonCreationConverter
  {
    Spécifications dérogatoires protégées Créer (Type objectType, JObject JsonObject)
    {
      if (JsonObject ["stockage"]! = null)
      {
        retourner nouveaux PhoneSpecs ();
      }

      if (JsonObject ["FullHD"]! = null)
      {
        retourner nouveaux TvSpecs ();
      }

      return null;
    }
  }
}
Enfin, pour obtenir ces convertisseurs utilisés par le désérialiseur vous devez modifier légèrement la ligne de désérialisation:
var = désérialisée JsonConvert.DeserializeObject <Liste <Device>> (r.EventArgs.Result, 
  nouveau JsonDeviceConverter (), nouveau JsonSpecsConverter ());

Et bien sûr, si vous mettez un point d'arrêt derrière cette ligne, vous pouvez placer une veille sur "désérialisées" et de voir que la structure de données a été désérialisé dans notre structure de classe habilement conçu.


Désérialisées

Et c'est tout ce qu'il ya à faire. solution de démo avec le code complet peut être consulté ici .

0 commentaires:

Enregistrer un commentaire

 
-