2017-12-03 194 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”来处理分页。 –

相关问题