简体   繁体   中英

Unable to read json comes from Web API in C#

Unable to read webapi value to a list object. Please see the screenshot value at the link http://prntscr.com/lcmw7q .

Error is Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (eg {"name":"value"}) into type 'System.Collections.Generic.List`1[StudentProfileClient.StudentInfo]' because the type requires a JSON array (eg [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'data', line 2, position 10.'

class StudentInfo
    {     




        public string cellPhone { get; set; }

        public string gender { get; set; }

        public string dateOfBirth { get; set; }
    }

 class RootClass
    {

        public int TotalCount { get; set; }
        public List<StudentInfo> stdinfo { get; set; }


    }
    static async Task GetData()
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://203.81.70.102:8092/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                HttpResponseMessage response;

                response = await client.GetAsync("control/qZkNkcGgWq6PiVbJzQ2=/student-profiles");

                if (response.IsSuccessStatusCode)
                {
                    List<StudentInfo> RootClass = new List<StudentInfo>();
                    RootClass = await response.Content.ReadAsAsync<List<StudentInfo>>();

                }

            }
        }

You can't directly deserialize from your API response using JsonConvert.DeserializeObject.

 JObject jsonResponse = JObject.Parse(jsonString);
    JObject objResponse = (JObject)jsonResponse["response"];
    Dictionary<string, JArray> _Data = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, JArray>>(objResponse.ToString());

Instead of declaring RootClass as List, use:

var RootClass = await response.Content.ReadAsAsync()

Put a breakpoint in the line, and check the Type that is returned from the API. As var will accept anything, you can check the response. Basically your error says that you are trying to CAST to an invalid type, so the deserialization is not working properly.

It seems the returning object is an array, maybe you need to get the array and convert it to a list, or even is a completly different object than the one you are expecting, have other properties, etc...

Best way to solve -> Debug, and make sure you are using the correct Type to deserialize

1) By using JObject in Newtonsoft.json .

Type below command in Package Manager Console.

Install-Package Newtonsoft.Json

if (response.IsSuccessStatusCode)
{
    string json = await response.Content.ReadAsStringAsync();

    JObject jObject = JObject.Parse(json);

    List<StudentInfo> studentInfos = jObject["data"].ToObject<List<StudentInfo>>();
}

Output:

在此处输入图片说明


2) By without using Newtonsoft.json .

Type below command in Package Manager Console.

Install-Package Microsoft.AspNet.WebApi.Client

if (response.IsSuccessStatusCode)
{
    RootClass rootClass = await response.Content.ReadAsAsync<RootClass>();

    List<StudentInfo> studentInfos = rootClass.data;
}

Output:

在此处输入图片说明

So your classes will be

public class StudentInfo
{
    public int sl { get; set; }
    public string studentId { get; set; }
    public string studentName { get; set; }
    public string school { get; set; }
    public string program { get; set; }
    public string fatherName { get; set; }
    public string motherName { get; set; }
    public string cellPhone { get; set; }
    public string gender { get; set; }
    public string dateOfBirth { get; set; }
}

public class RootClass
{
    public List<StudentInfo> data { get; set; }
    public string message { get; set; }
    public int total { get; set; }
}

simple solution, you need a wrapper

What does this look like in practice? It simply means that APIs that return lists of objects wrap the list in a top-level object. For example, suppose you have a Person data type in your API. If you GET a single Person, you might end up with the following JSON response:

{ "name": "John Smith" }

All's well so far. But what if you want a list instead of a single one? The most intuitive way might be as follows:

[{"name": "John Smith"}, {"name": "Jane Smith"}]

But that's exactly the situation we need to avoid. As a result we need to use a top-level object for lists such as this, with a single data property:

{"data": [{"name": "John Smith"}, {"name": "Jane Smith"}]}

so.....

Class Students{
public List<StudentInfo> roots{get;set;}

}

keep your student class, add my class students, and deserialize to that;

So you've got a class called RootClass. And you've got a class called StudentInfo.

Which one do you expect to get? Seems that you're getting something totally different. As I see here, https://prnt.sc/lcnlho , you should create a new class (or change RootClass structure) that will look like this

 class ResponseContainer
    {
        public List<StudentInfo> data { get; set; }
    }

And instead of deserializing straight into List, you should deserialize to this ResponseContainer class:

var response = await response.Content.ReadAsAsync<ResponseContainer>();

ps If you want to use your RootClass, you should either rename the property stdinfo to "data", or add JsonProperty attribute like this:

 class RootClass
    {
        public int TotalCount { get; set; }

        [JsonProperty(PropertyName = "data")]
        public List<StudentInfo> stdinfo { get; set; }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM