2016-07-13 82 views
2

我有這樣的JSON:反序列化JSON到自定義列表

var x = [ 
    [99,"abc","2dp",{"GroupNum": 0,"Total":[4, 1]}], 
    [7,"x","date"], 
    [60,"x","1dp",{"GroupNum": 1}], 
    ... 
] 

以下規則存在(讓i指內部列表索引):

  • x[i][0] - 強制項目 - 總是整數
  • x[i][1] - 強制項目 - 總是一個字符串
  • x[i][2] - 強制項目 - 總是一個字符串
  • x[i][3] - 可選項 - 當它存在,那麼它有以下規則:
    • x[i][3].GroupNum - 必填字段 - 總是整數
    • x[i][3].Total - 可選字段 - 當它存在,那麼它是整數
    • 名單

所以我創建了下面的類規則:

public class ReportTemplateField : System.Collections.CollectionBase 
{ 
    public object this[int index] 
    { 
     get 
     { 
      switch (index) 
      { 
       case 0: 
        return (int)List[index]; 
       case 1: 
       case 2: 
        return (string)List[index]; 
       case 3: 
        return (ReportGrouping)List[index]; 
       default: 
        throw new System.ArgumentOutOfRangeException("Class ReportTemplateField only contains 4 items"); 
      } 
     } 
     set 
     { 
      switch (Count) 
      { 
       case 0: 
        List[index] = unchecked((int)value); 
        break; 
       case 1: 
       case 2: 
        List[index] = (string)value; 
        break; 
       case 3: 
        List[index] = (ReportGrouping)value; 
        break; 
       default: 
        throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items"); 
      } 
     } 
    } 

    public void Add(object item) 
    { 
     switch (Count) 
     { 
      case 0: 
       List.Add(unchecked((int)item)); 
       break; 
      case 1: 
      case 2: 
       List.Add((string)item); 
       break; 
      case 3: 
       List.Add((ReportGrouping)item); 
       break; 
      default: 
       throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items"); 
     } 
    } 
} 

public class ReportGrouping 
{ 
    public int GroupNum { get; set; } 
    public List<int> Total { get; set; } 
} 

然而,當我嘗試使用json.net反序列化時,ReportTemplateField類永遠不會被使用。我知道這是因爲我已經把斷點在每一個方法,其中沒有被觸發:

string json = "[[99,\"abc\",\"2dp\",{\"GroupNum\": 0,\"Total\":[4, 1]}],[7,\"x\",\"date\"],[60,\"x\",\"1dp\",{\"GroupNum\": 1}]]"; 
List<ReportTemplateField> parsed = JsonConvert.DeserializeObject<List<ReportTemplateField>>(json); 
int Total01 = parsed[0][3].Total[1]; 

給了我這個錯誤:

error CS1061: 'object' does not contain a definition for 'Total' and no extension method 'Total' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

但是它的工作原理,如果我只是反序列化隔離ReportGrouping

string json2 = "{\"GroupNum\": 0,\"Total\":[4, 1]}"; 
ReportGrouping parsed2 = JsonConvert.DeserializeObject<ReportGrouping>(json2); 
parsed2.Total[1]; // 1 

所以問題在於ReportTemplateField類。也許我不應該從System.Collections.CollectionBase繼承?我基本上按照這個步驟做了一些修改 - https://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx但它確實說文檔可能已經過時。我正在使用.NET 4.5,所以請將其納入您的任何答案。

我該如何讓Json.net正確反序列化,這樣我才能去parsed[0][3].Total[1];訪問第二個總數的整數值,而不需要對它進行任何操作或完成任何操作?

+0

你的'x'「Json」只是僞代碼?我很挑剔,但它不是一個有效的Json字符串 –

+0

它的JavaScript。但這對於這個問題並不重要。只要按'string json = ...'一半往下走 - 它是一樣的。你可以省略'...' - 這只是暗示主列表中有更多的列表。 – mulllhausen

+0

很酷,是的,我得到了'...'位 - 只是想檢查。如果它對你有幫助,我喜歡從Json對象創建C#類並將它們解析出來。嘗試使用:http://json2csharp.com如果你在那裏發佈了一些實際的原生Json,你會在另一端得到一些整潔的C#類。 (部分原因是我問Json的原因,我會嘗試粘貼一些,看看它是如何變成的)。然後JsonConvert類可以解析它們並填充你的C#類。我懷疑你的錯誤是使用'System.Collections.CollectionBase'推導 –

回答

2

有一個在碼數的錯誤,1是該對象不具有所謂的總性能和另一個是解析[0] [3]是一個字符串。

你必須在代碼中幾個錯誤:

  1. 解析[0] [3]是一個字符串。通過將字符串轉換爲ReportGrouping來修復它。
  2. 新ReportGrouping()。組名應根據Json的命名組。
  3. 你解析後解析[0] [3]爲ReportingGroup它仍然會返回一個對象,所以我投成ReportingGroup之後。即(ReportingGroup)解析[0] [3]。

    get 
    { 
        switch (index) 
        { 
         case 0: 
          return (int)List[index]; 
         case 1: 
         case 2: 
          return (string)List[index]; 
         case 3: 
          return JsonConvert.DeserializeObject<ReportGrouping>(List[index].ToString()); 
         default: 
          throw new System.ArgumentOutOfRangeException("Class ReportTemplateField only contains 4 items"); 
        } 
    } 
    

而且使用這樣的:

List<ReportTemplateField> parsed = JsonConvert.DeserializeObject<List<ReportTemplateField>>(json); 
ReportGrouping group = (ReportGrouping)parsed[0][3]; 

不要忘了組名重命名成集團和修復二傳手。

編輯:對不起,重複自己很多次..

+0

非常感謝您的關注!但爲什麼你說這個對象沒有一個名爲'Total'的屬性? 'ReportGrouping'中存在'Total'(位於C#代碼示例的底部)。此外,我會修復問題中的json,因爲這只是我的代碼的以前版本遺留的錯字。 – mulllhausen

+0

另外,任何想法爲什麼setter永遠不會被json.net調用?我嘗試在setter中放置一個斷點,但它永遠不會被觸發。 – mulllhausen

+1

解析[0] [3]返回類對象的類型的項(那對吸氣劑什麼指定)。然後,您需要將其轉換爲具有屬性Total的類類型ReportGrouping。然後通過編寫(ReportGrouping)來轉換它。 – Hyperdingo