繁体   English   中英

无法读取来自 C# 中的 Web API 的 json

[英]Unable to read json comes from Web API in C#

无法将 webapi 值读取到列表对象。 请查看链接http://prntscr.com/lcmw7q 中的屏幕截图值。

错误是Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (eg {"name":"value"}) 到 type 'System.Collections.Generic.List`1[StudentProfileClient.StudentInfo]' 因为该类型需要一个JSON 数组(例如 [1,2,3])以正确反序列化。 要修复此错误,请将 JSON 更改为 JSON 数组(例如 [1,2,3])或更改反序列化类型,使其成为正常的 .NET 类型(例如,不是像整数这样的原始类型,而不是像这样的集合类型)可以从 JSON 对象反序列化的数组或列表)。 JsonObjectAttribute 也可以添加到类型中以强制它从 JSON 对象反序列化。 路径“数据”,第 2 行,位置 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>>();

                }

            }
        }

您不能使用 JsonConvert.DeserializeObject 从 API 响应中直接反序列化。 ——

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

不要将 RootClass 声明为 List,而是使用:

var RootClass = 等待 response.Content.ReadAsAsync()

在行中放置一个断点,并检查从 API 返回的类型 由于 var 将接受任何内容,您可以检查响应。 基本上,您的错误表明您正在尝试将 CAST 转换为无效类型,因此反序列化无法正常工作。

似乎返回的对象是一个数组,也许您需要获取该数组并将其转换为列表,或者甚至是与您期望的对象完全不同的对象,具有其他属性等...

解决的最佳方法 ->调试,并确保您使用正确的类型进行反序列化

1) 通过在Newtonsoft.json使用JObject

在包管理器控制台中键入以下命令。

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>>();
}

输出:

在此处输入图片说明


2) 不使用Newtonsoft.json

在包管理器控制台中键入以下命令。

Install-Package Microsoft.AspNet.WebApi.Client

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

    List<StudentInfo> studentInfos = rootClass.data;
}

输出:

在此处输入图片说明

所以你的课程将是

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; }
}

简单的解决方案,你需要一个包装器

这在实践中是什么样子的? 它只是意味着返回对象列表的 API 将列表包装在顶级对象中。 例如,假设您的 API 中有一个 Person 数据类型。 如果您 GET 一个 Person,您最终可能会得到以下 JSON 响应:

{ "name": "John Smith" }

到目前为止一切都很好。 但是如果你想要一个列表而不是一个列表呢? 最直观的方式可能如下:

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

但这正是我们需要避免的情况。 因此,我们需要为这样的列表使用顶级对象,并具有单个数据属性:

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

所以.....

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

}

保留你的学生班级,添加我班级的学生,然后反序列化;

所以你有一个叫做 RootClass 的类。 您有一个名为 StudentInfo 的类。

你希望得到哪一个? 似乎你得到了完全不同的东西。 正如我在这里看到的, https: //prnt.sc/lcnlho ,您应该创建一个新类(或更改 RootClass 结构),如下所示

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

而不是直接反序列化到 List,你应该反序列化到这个 ResponseContainer 类:

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

ps 如果你想使用你的 RootClass,你应该将属性 stdinfo 重命名为“data”,或者像这样添加 JsonProperty 属性:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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