2017-07-05 64 views
0

我是C#中的一個begginer,一直在努力解決這個問題。Deserialise JSON並獲取數據類型

  1. 我有一個Json文件。
  2. 我需要對其進行反序列化並將數據插入到SQL中。
  3. JSON文件看起來是這樣的:

    { 
        "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. 到目前爲止我的代碼:

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

詳情:

的想法是刪除一切,是在數據庫並在每次運行時重新創建所有內容。所以它會刪除/刪除表格並用最新的數據重新創建同一個表格。例如對於Users表,如果有(從昨天運行的)Users_temp表存在,那麼將首先刪除,然後創建Users_temp表,將最新數據插入此表,然後刪除Users表,然後將Users_temp重命名爲Users表。我的問題在於,爲了創建Users_temp表,我必須定義它的列類型。所以我必須得到first_name的數據類型,它將以字符串形式出現,然後我必須以某種方式將它映射到varchar(255),然後構建sql語句。

創建表的用戶( 如first_name VARCHAR(255) 姓氏VARCHAR(255) 時區的日期時間 );

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

現在發生什麼事了,一切都被解析爲字符串。即使時區或任何int數據也被解析爲字符串。所以我無法構建sql語句,因爲我沒有得到正確的數據類型。我假定這是因爲這些線路:

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

,因爲我的項目轉換爲itemString,一切都變得字符串。 JsonConvert.DeserializeObject只接受String參數,所以我無法通過其他任何東西。有什麼方法可以在那裏恢復原始數據類型?

+0

若它沒有任何地方一起傳遞。在這一點上,您最好的猜測是創建一個可以在JSON中包含一行的模型,並根據您的模型將反序列化轉換或解析值。 –

+0

謝謝蒂莫西。是的,我想製作一個模型,但正如你看到的類「用戶」和類ABC在「字段」節點中有不同的值。 json文件中有成千上萬個類,我無法爲每個類使用一個模型。而且,對我的要求是,它必須足夠動態才能接收和解析將來或將來可能出現的任何類類型,並獲取其數據類型並動態地插入表中。如果沒有將json去除到相應的類中,我該怎麼做? – freshman8

+0

這是非常棘手的,也許假設基於數據在JSON中被註釋的方式的「安全」大/安全的數據類型? (如果包裹在''「'中,但不是日期符號,它可能是一個'string',如果沒有包裝並且沒有小數點,假設它是一個'long',如果它有一個小數點,假設一個'decimal',等)? –

回答

0

如果在json字符串中找不到它們,可以使用類型化模型並告訴JsonConvert將字段留爲空。您可以利用它並在類型化模型結構中提供所有可能的字段。在數據進入數據庫之前,您可以獲得驗證數據的正確類型的好處。

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

爲了JsonConvert意識到可能丟失的字段爲此,您需要轉換之前進行以下設置:

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