使用Newtonsoft和bide View(MVVM)反序列化JSON

时间:2017-12-03 04:38:12

标签: c# json mvvm xamarin.forms json.net

我是C#和Xamarin的初学者。我试图用newtonsoft反序列化json数组? 这是我的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; }
    }




当我尝试反序列化为List时,它会在此行引发异常:



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

错误是:

  

附加信息:无法将当前JSON对象(例如{&#34; name&#34;:&#34; value&#34;})反序列化为类型System.Collections.Generic.List`1 [ System.Object的]&#39;因为该类型需要JSON数组(例如[1,2,3])才能正确反序列化。

     

要修复此错误,请将JSON更改为JSON数组(例如[1,2,3])或更改反序列化类型,使其成为普通的.NET类型(例如,不是像整数这样的基本类型,而不是可以从JSON对象反序列化的集合类型,如数组或List)。 JsonObjectAttribute也可以添加到类型中以强制它从JSON对象反序列化。

这段代码绝对是Json,但我现在不会检索数据并填充该类:

&#13;
&#13;
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;
        }
&#13;
&#13;
&#13;

我已经在MainViewModel中创建了一些代码,但我不知道如何检索数据并插入类Item:

&#13;
&#13;
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
    }
}
&#13;
&#13;
&#13;

RootItemViewModel类:

&#13;
&#13;
    public class RootItemViewModel : RootObject
    {

       
    }
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分: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

你不能把List放到因为JSON对象不是纯List Of对象,它是下一个对象和items对象之间的组合对象。因此,在将JSON放入列表之前,您需要先创建一个类。

答案 1 :(得分:0)

http://json2csharp.com/总是很有用,(快速获取课程&#39;骨架&#39;)

喜欢&#39; Hery先生&#39;写道你可能不得不做自定义阅读器或删除$符号 - 如果你自己生成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);

答案 2 :(得分:0)

1)您的Json响应显示,它只包含RootObject类型的实例。

2) var data = JsonConvert.DeserializeObject<List<RootObject>>(json); 不会,因为您尝试将RootObject投射到List<RootObject>。在您的错误回复中描述。

3) dynamic jsonDe = JsonConvert.DeserializeObject<RootObject>(json);会有效,因为在此您将RootObject投射到RootObject。我也建议你使用&#34; var&#34;而不是&#34;动态&#34; (见原因: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类型的属性。

我希望我能搞清楚!