2017-07-05 3 views
0

Je suis un begginer en C# et j'ai eu du mal à résoudre ce problème.Désérialise JSON et obtient les types de données

  1. J'ai un fichier Json.
  2. Je dois le désérialiser et insérer les données dans SQL.
  3. Le fichier JSON ressemble à ceci:

    { 
        "records": [ 
        { 
         "class": "Abc", 
         "id": "7720170378514849999", 
         "fields": { 
          "name": "xyz", 
          "created_at": "2015-02-26 15:06:48 UTC", 
          "updated_at": "2017-05-08 15:31:45 UTC", 
          "domain": "domainname", 
          "month": null, 
          "secure": true, 
          "filters": null, 
          "users_counter": 373 
         }, 
         "links": { 
         } 
        }, 
        { 
         "class": "User", 
         "id": "7765907511856219999", 
         "fields": { 
          "first_name": "aaa", 
          "last_name": "bbb", 
          "email": "[email protected]", 
          "timezone": null, 
          "local": null, 
          "unsubscribe": false, 
          "address_verified": false 
         }, 
         "links": { 
          "Abc_id": "7720170378514849999" 
         } 
        }, 
    } 
    
  4. Mon code à ce jour:

    public void doConvert() 
    { 
        string unzippedFileName = "c:\\tar\\finish\\UnzippedFile.json"; 
    
    
        List<dynamic> allEntities = new List<dynamic>(); 
    
        try 
        { 
         var deserialisedJson = JsonConvert.DeserializeObject<dynamic> 
         (System.IO.File.ReadAllText(@unzippedFileName)); 
         var records = deserialisedJson.records; 
    
         foreach (var item in records) 
         { 
          string itemString = item.ToString(); 
          var deserialisedItem = 
          JsonConvert.DeserializeObject<Dictionary<dynamic, dynamic>> 
          (itemString); 
          var className = deserialisedItem["class"]; 
          var classId = deserialisedItem["id"]; 
          dynamic classFields = deserialisedItem["fields"]; 
    
          var deserialisedClassFields = 
          JsonConvert.DeserializeObject<Dictionary<dynamic, dynamic>> 
          (classFields.ToString()); 
    
          dynamic classLinks = deserialisedItem["links"]; 
          var deserialisedClassLinks = JsonConvert.DeserializeObject<Dictionary<dynamic, dynamic>>(classLinks.ToString()); 
    
    
          ParseIntoType(className);      
          ParseIntoType(classId); 
    
    
    
          foreach (KeyValuePair<dynamic, dynamic> entry in deserialisedClassFields) 
          { 
           ParseIntoType(entry.Key); 
          } 
    
          foreach (KeyValuePair<dynamic, dynamic> entry in deserialisedClassLinks) 
          { 
           ParseIntoType(entry.Key); 
          } 
    
    
          buildsqlstatements() // My issue is here 
    
    
         } 
    
        } 
        catch (Exception ee) 
        { 
         Log.ErrorFormat("Exception:{0}", ee.ToString()); 
        } 
    } 
    
    public void ParseIntoType(dynamic itemTobeParsed) 
    { 
    
        new Dictionary<Type, Action>{ 
         {typeof(bool),() => boolEntityList.Add(itemTobeParsed)}, 
         {typeof(int), () => intEntityList.Add(itemTobeParsed)}, 
         {typeof(BigInteger), () => bigIntEntityList.Add(itemTobeParsed)}, 
         {typeof(double), () => doubleEntityList.Add(itemTobeParsed)}, 
         {typeof(DateTime), () => dateTimeEntityList.Add(itemTobeParsed)}, 
         {typeof(string), () => stringEntityList.Add(itemTobeParsed)}, 
         {typeof(TextReader), () => textEntityList.Add(itemTobeParsed)},    
    
         }[itemTobeParsed.GetType()](); 
    
    
    } 
    

Détails:

L'idée est de supprimer tout ce qui est en la base de données et recréer tout à chaque exécution. Donc, il va supprimer/supprimer les tables et recréer la même table avec les dernières données. Par exemple pour la table Users, je vais d'abord supprimer la table Users_temp, puis créer la table Users_temp, insérer les dernières données dans cette table, puis supprimer la table Users, puis renommer Users_temp en table Users . Mon problème ici est que pour créer la table Users_temp, je dois définir ses types de colonnes. Donc, je dois obtenir le type de données de first_name, qui entrerait en tant que chaîne, puis je devrais le mapper en quelque sorte à varchar (255) et ensuite construire l'instruction sql.

Création d'utilisateurs de table ( prenom varchar (255) varchar lastname (255) fuseau horaire datetime );

  //string createTmpTable = "create table "+className+" ((column = deserialised key from fields, datatype = its datatype))"; 

Maintenant, tout ce qui se passe est analysé comme une chaîne de caractères. Même le fuseau horaire ou toutes les données int est également analysé en tant que chaîne. Je suis donc incapable de générer l'instruction sql car je ne reçois pas le type de données correct. Je suppose que c'est à cause de ces lignes:

foreach (var item in records) 
      { 
       string itemString = item.ToString(); 
       var deserialisedItem = 
    JsonConvert.DeserializeObject<Dictionary<dynamic, dynamic>>(itemString); 

parce que je suis en train de convertir l'élément à itemString, tout devient une chaîne. JsonConvert.DeserializeObject ne prend que le paramètre String, donc je ne peux rien y passer d'autre. Est-il possible de récupérer le type de données d'origine là-bas?

+0

Pas si ce ne sont pas transmises partout. votre meilleure estimation à ce stade est de faire un modèle qui pourrait contenir une ligne dans votre JSON, et de faire de votre désérialisation en lançant ou en analysant les valeurs en fonction de votre modèle. –

+0

Merci Timothy. Oui j'ai pensé faire un modèle mais comme vous voyez la classe Utilisateurs et classe Abc ont des valeurs différentes dans le noeud "champs". Il y a des milliers de classes dans le fichier json et je ne peux pas utiliser un modèle pour chaque classe.De plus, l'exigence qui m'est imposée est que cela doit être assez dynamique pour recevoir et analyser n'importe quel type de classe qui arrive ou qui pourrait venir, obtenir son type de données et l'insérer dans la table dynamiquement. Comment ferais-je cela sans déseraliser le json à sa classe respective? – freshman8

+0

qui est assez difficile, peut-être supposer des types de données "sûrs" de grande taille/sûr basé sur la façon dont les données sont notées dans JSON? (si enveloppé dans '" "', mais pas une notation de date, c'est probablement une chaîne, si ce n'est pas encapsulé et sans point décimal, supposons que c'est un long, s'il a un point décimal, supposons un point décimal, etc?) –

Répondre

0

Vous pouvez utiliser un modèle typé et dire à JsonConvert de laisser les champs vides s'il ne les trouve pas dans la chaîne json. Vous pouvez tirer parti de cela et fournir tous les champs possibles dans une structure de modèle typée. Vous gagnez l'avantage de vérifier que les données sont correctement tapées avant qu'elles ne pénètrent dans la base de données.

public class Record 
{ 
    public string @class {get; set;} 
    public string id { get; set; } 
    public List<RecordField> fields { get; set; } 
    public Dictionary<string,string> links { get; set; } 
} 

public class RecordField 
{ 
    // fields from first object in the array 
    public string name { get; set; } 
    public DateTime created_at { get; set; } 
    public DateTime updated_at { get; set; } 
    public string domain { get; set; } 
    public int month { get; set; } 
    public bool secure { get; set; } 
    public List<string> filters { get; set; } 
    public int user_count { get; set; } 

    // fields from second object in the array 
    public int first_name { get; set; } 
    //... 
} 

Pour faire connaître JsonConvert des champs manquants possibles cela, vous devez définir les paramètres suivants avant la conversion:

var settings = 
    new JsonSerializerSettings 
    { 
     NullValueHandling = NullValueHandling.Ignore, 
     MissingMemberHandling = MissingMemberHandling.Ignore 
    }; 
var records = JsonConvert.DeserializeObject<List<Record>>(json, settings);