2017-12-03 273 views
1

我是C#和Xamarin的初學者。我想用newtonsoft反序列化json數組? 這裏是我的JSON文件:反序列化使用Newtonsoft和biding查看(MVVM)的JSON

{ 
 
    "next": { 
 
     "$ref": "http://192.168.0.100:8080/ords/hr/employees/?page=1" 
 
    }, 
 
    "items": [ 
 
     { 
 
      "empno": 7369, 
 
      "ename": "SMITH", 
 
      "job": "CLERK", 
 
      "mgr": 7902, 
 
      "sal": 800, 
 
      "deptno": 20 
 
     }, 
 
     { 
 
      "empno": 7934, 
 
      "ename": "MILLER", 
 
      "job": "CLERK", 
 
      "mgr": 7782, 
 
      "sal": 1300, 
 
      "deptno": 10 
 
     } 
 
    ] 
 
}

她是我的模型類:

public class RootObject 
 
    { 
 
     [JsonProperty("items")] 
 
     public Item[] Items { get; set; } 
 

 
     [JsonProperty("next")] 
 
     public Next Next { get; set; } 
 
    } 
 

 
    public class Next 
 
    { 
 
     [JsonProperty("$ref")] 
 
     public string Ref { get; set; } 
 
    } 
 

 
    public class Item 
 
    { 
 
     [JsonProperty("deptno")] 
 
     public long Deptno { get; set; } 
 

 
     [JsonProperty("empno")] 
 
     public long Empno { get; set; } 
 

 
     [JsonProperty("ename")] 
 
     public string Ename { get; set; } 
 

 
     [JsonProperty("job")] 
 
     public string Job { get; set; } 
 

 
     [JsonProperty("mgr")] 
 
     public long Mgr { get; set; } 
 

 
     [JsonProperty("sal")] 
 
     public long Sal { get; set; } 
 
    }

當我嘗試反序列化到一個列表它拋出異常此行:

var data = JsonConvert.DeserializeObject<List<RootObject>>(json);

錯誤是:

其他信息:不能反序列化當前JSON對象(例如{「name」:「value」})類型爲'System.Collections.Generic.List`1 [System.Object]',因爲類型需要JSON數組(例如[1,2,3])才能正確地反序列化。

要修復此錯誤,請將JSON更改爲JSON數組(例如[1,2,3])或更改反序列化類型,以使其成爲正常的.NET類型(例如,不是像整數這樣的基本類型,不是像數組或List的集合類型),可以從JSON對象反序列化。 JsonObjectAttribute也可以添加到類型中,以強制它從JSON對象反序列化。

此代碼desirialize JSON的,但我現在不retrive數據並填充類:

public class ApiServices { 
 

 

 
     public async Task<RootObject> GetRootObject() 
 
     { 
 
      var client = new HttpClient(); 
 
      var url = string.Format("http://mysite/ords/hr/employees"); 
 
      var response = await client.GetAsync(url); 
 

 
      var json = await response.Content.ReadAsStringAsync(); 
 

 
      dynamic jsonDe = JsonConvert.DeserializeObject<RootObject>(json); 
 

 
      return jsonDe; 
 
     }

我已經創造了一些代碼MainViewModel,但我不知道如何檢索數據並插入類別項目:

public class MainViewModel 
 
    { 
 
     #region Properties 
 
     
 
     public ObservableCollection<RootItemViewModel> RootObjects { get; set; } 
 

 
     private ApiServices apiServices; 
 

 
     #endregion 
 

 
     #region Constructors 
 
     public MainViewModel() 
 
     { 
 
      //Create observable collections 
 
      RootObjects = new ObservableCollection<RootItemViewModel>(); 
 

 
      //Instance services 
 
      apiServices = new ApiServices(); 
 

 
      //Load Data 
 
      LoadData(); 
 
     } 
 
     #endregion 
 

 
     #region Methods 
 

 

 
     private async void LoadData() 
 

 
     { 
 
      var emps = new RootObject(); 
 
         
 
      emps = await apiServices.GetRootObject(); 
 

 
      RootObjects.Clear(); 
 

 
      foreach (var item in RootObjects) 
 
      { 
 

 
       RootObjects.Add(new RootItemViewModel 
 
       { 
 

 

 
       }); 
 
      } 
 
     } 
 
      
 
     #endregion 
 
    } 
 
}

類RootItemViewModel:

public class RootItemViewModel : RootObject 
 
    { 
 

 
     
 
    }

+3

嘗試JsonConvert.DeserializeObject (json);你的json頂層是一個對象而不是列表。 – Cedar

回答

0

1)你的JSON響應所示,它只是保持型RootObject的一個實例。

2)var data = JsonConvert.DeserializeObject<List<RootObject>>(json);不會工作,因此,因爲您嘗試投下RootObjectList<RootObject>。在錯誤響應中描述。

3)dynamic jsonDe = JsonConvert.DeserializeObject<RootObject>(json);將工作因爲在這裏你施放RootObjectRootObject。我也建議你塗用,而不是 「動態」 的 「變種」(明白爲什麼:dynamic vs var

4)你下面的方法似乎有沒有搞錯:

private async void LoadData() 
{ 
    var emps = new RootObject(); 

    emps = await apiServices.GetRootObject(); 

    RootObjects.Clear(); 

    //Mistake: 
    //You iterate through the previously cleared observable collection. 
    //it really should be "foreach (var item in emps.Items)" 
    foreach (var item in RootObjects) 
    { 

     RootObjects.Add(new RootItemViewModel 
     { 


     }); 
    } 
} 

5)它看起來像你想與Item類型的數組養活觀察集合你的RootObject

public class RootObject 
    { 
     [JsonProperty("items")] 
     public Item[] Items { get; set; } //This property 

     [JsonProperty("next")] 
     public Next Next { get; set; } 
    } 

那麼你實際上應該做的是設置這樣的數據:

private async void GetRootObjectItems() 
     { 
      RootObject emps = await apiServices.GetRootObject(); //Get the root object 
      RootObjects.Clear();      //clear the list 

      foreach (var item in emps.Items) //Important, to get the data from the Array on the RootObject 
      { 
       ///its a nice way to give your viewmodel a ctor signature that ensures a correct initialization 
       ///public RootItemViewModel(Item item) 
       ///{ 
       /// this.Deptno = item.Deptno; 
       ///} 
       RootObjects.Add(new RootItemViewModel(item)); 
      } 
     } 
    } 

6)這是沒有意義的你RootItemViewModelRootObject繼承。你應該讓它從Item繼承或擁有Item類型的財產。

我希望我能清理一下!

+1

很好的例子!謝謝。代碼工作!和我的觀點是綁定到視圖模型 –

+0

太棒了!也謝謝你 – Csharpest

0

對於此JSON:

{ 
"next": { 
    "$ref": "http://192.168.0.100:8080/ords/hr/employees/?page=1" 
}, 
"items": [ 
    { 
     "empno": 7369, 
     "ename": "SMITH", 
     "job": "CLERK", 
     "mgr": 7902, 
     "sal": 800, 
     "deptno": 20 
    }, 
    { 
     "empno": 7934, 
     "ename": "MILLER", 
     "job": "CLERK", 
     "mgr": 7782, 
     "sal": 1300, 
     "deptno": 10 
    } 
] 

}

使用這個類:

internal class SomeObject{ //in C# you can even NOT to define internal as well :) 
public class next{ 
    public string ref {get; set;} //var do not use $, you need to change the JSON code or you nned to make a custom reader for that. 
} 

public List<Item> items {get; set;} 

public class Item{ 
    public string empno {get; set;} 
    public string ename {get; set;} 
    public string job {get; set;} 
    public string mgr {get; set;} 
    public string sal {get; set;} 
    public string deptno {get; set;} 
} 
} 

反序列化的JSON到一個類,用這一個:

var obj = JSONConvert.DeserializeObject<SomeObject>(json); //json is a string of your JSON 

//Now you can access the data like 

listView.ItemsSource = obj.Items; //for mobile listview 

你不能把名單,因爲JSON對象不是純粹的List對象,它結合下一個對象和項目對象之間的對象。因此,在將JSON放入列表之前,您需要先創建一個類。

+0

感謝您的回覆Mr Hery! –

0

http://json2csharp.com/總是有用的,(快速的方法來獲取類「骨架」)

像'Hery先生寫給你可能要做一個自定義的閱讀器或刪除$符號 - 如果要生成的JSON輸出你自己。

public class Next 
{ 
    public string @ref { get; set; } 
} 

public class Item 
{ 
    public int empno { get; set; } 
    public string ename { get; set; } 
    public string job { get; set; } 
    public int mgr { get; set; } 
    public int sal { get; set; } 
    public int deptno { get; set; } 
} 

public class RootObject //(rename class you something better like Employees) 
{ 
    public Next next { get; set; } 
    public List<Item> items { get; set; } 
} 

對於反序列化:

var data = JsonConvert.DeserializeObject<RootObject>(json); 

var _employees = JsonConvert.DeserializeObject<Employees>(json); 
+0

謝謝@ bomanden。 Oracle自動生成對象「next」來處理分頁。 –

相關問題