2017-07-05 3 views
0

Ich bin ein Anfänger in C# und habe gekämpft, um dieses Problem zu lösen.Deserialise JSON und die Datentypen

  1. Ich habe eine JSON-Datei.
  2. Ich muss es deserialisieren und die Daten in SQL einfügen.
  3. Die Json-Datei sieht etwa so aus:

    { 
        "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. Mein Code so weit:

    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()](); 
    
    
    } 
    

Details:

Die Idee ist, alles zu löschen, die in ist die Datenbank und neu erstellen alles bei jedem Lauf. So wird es die Tabellen löschen/löschen und die gleiche Tabelle mit den neuesten Daten neu erstellen. Zum Beispiel für Benutzer Tabelle, ich werde zuerst fallen, wenn eine (von gestern) Users_temp Tabelle dort ist, dann erstellen Users_temp Tabelle, fügen Sie die neuesten Daten in diese Tabelle, dann fallen Benutzer Tabelle und dann umbenennen Users_temp Benutzer Tabelle . Mein Problem hier ist, dass, um die Tabelle Users_temp zu erstellen, ich seine Spaltentypen definieren muss. Also muss ich den Datentyp von first_name erhalten, der als String kommen würde und dann muss ich ihn irgendwie auf varchar (255) abbilden und dann die sql-Anweisung erstellen.

Tabelle Benutzer erstellen ( first_name varchar (255) Nachname varchar (255) Zeitzone Datumzeit );

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

Im Moment wird alles als Zeichenfolge geparst analysiert. Sogar die Zeitzone oder irgendwelche int-Daten werden als String analysiert. Daher kann ich die SQL-Anweisung nicht erstellen, weil ich nicht den richtigen Datentyp erhalte. Ich gehe davon aus, weil diese Zeilen ist:

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

, weil ich den Artikel itemString bin Umwandlung, alles, was ein String wird. JsonConvert.DeserializeObject nimmt nur String-Parameter, so dass ich dort nichts anderes übergeben kann. Gibt es eine Möglichkeit, den ursprünglichen Datentyp dort wiederherzustellen?

+0

Nicht, wenn es entlang überall nicht weitergegeben wird. Ihre beste Vermutung an diesem Punkt ist, ein Modell zu erstellen, das eine Zeile in Ihrem JSON enthalten kann, und Ihre Deserialisierung kann die Werte entsprechend Ihrem Modell umwandeln oder analysieren. –

+0

Danke Timothy. Ja, ich dachte daran, ein Modell zu erstellen, aber wie Sie sehen, haben die Klasse Benutzer und die Klasse Abc unterschiedliche Werte im Knoten "Felder". Es gibt Tausende von Klassen in der JSON-Datei und ich kann kein Modell für jede Klasse verwenden.Darüber hinaus ist die Anforderung, die mir gegeben wird, dass sie dynamisch genug sein muss, um jeden Klassentyp, der in Zukunft kommt oder kommen wird, zu empfangen und zu analysieren, seinen Datentyp zu erhalten und dynamisch in die Tabelle einzufügen. Wie würde ich das tun, ohne den JSON zu seiner jeweiligen Klasse zu deseralisieren? – freshman8

+0

das ist ziemlich schwierig, vielleicht "sichere" große/sichere Datentypen basierend auf der Art, wie die Daten in JSON notiert werden? (wenn es in "" ", aber nicht in eine Datumsnotation eingeschlossen ist, ist es wahrscheinlich eine" Zeichenkette ", wenn nicht umbrochen und keine Dezimalpunkte, nehme an, dass es ein' long' ist, wenn es einen Dezimalpunkt hat, nehme eine 'dezimal' an, usw.?) –

Antwort

0

Sie können ein typisiertes Modell verwenden und JsonConvert anweisen, Felder als null zu belassen, wenn sie in der JSON-Zeichenfolge nicht gefunden werden können. Sie können dies nutzen und alle möglichen Felder in einer typisierten Modellstruktur bereitstellen. Sie haben den Vorteil, dass die Daten korrekt getippt werden, bevor sie in die Datenbank gelangen.

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; } 
    //... 
} 

Um JsonConvert auf mögliche fehlende Felder diese Sie folgende Einstellungen vor der Konvertierung festlegen müssen:

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