Невозможно прочитать json из веб-api на c#

Невозможно прочитать значение webapi для объекта списка. Пожалуйста, посмотрите значение скриншота по ссылке http://prntscr.com/lcmw7q.

Ошибка Newtonsoft.Json.JsonSerializationException: 'Невозможно десериализовать текущий объект JSON (например, {"name": "value"}) в тип' System.Collections.Generic.List`1 [StudentProfileClient.StudentInfo] ', поскольку для типа требуется JSON массив (например, [1,2,3]) для правильной десериализации. Чтобы исправить эту ошибку, либо измените JSON на массив JSON (например, [1,2,3]), либо измените десериализованный тип, чтобы он был обычным типом .NET (например, не примитивным типом, таким как целое число, а не типом коллекции, например массив или список), который можно десериализовать из объекта JSON. JsonObjectAttribute также можно добавить к типу, чтобы заставить его десериализоваться из объекта JSON. Путь 'data', строка 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>>();

                }

            }
        }

Вы не можете напрямую десериализовать свой ответ API с помощью JsonConvert.DeserializeObject.

Mandar Dhadve 31.10.2018 12:18

Подскажите, пожалуйста, где мне исправить свой код ... Я буду очень полезен

Md. Rayhan Khan 31.10.2018 12:19

Все это пустышка. Спасибо за предупреждение ...

Md. Rayhan Khan 31.10.2018 12:30

@ Md.Rayhan Khan, не могли бы вы показать свой json?

er-sho 31.10.2018 12:47
prntscr.com/lcnlho
Md. Rayhan Khan 31.10.2018 13:03

@ Md.RayhanKhan, я имею в виду, не могли бы вы добавить этот образец json в свой вопрос?

er-sho 31.10.2018 13:10

После просмотра предоставленного JSON в "prntscr.com/lcnlho" кажется, что ваши модели неверны, объект идентификатора ответа и вы анализируете его как массив, предоставьте Json в текстовом формате, и я укажу, как его исправить.

Mihir Dave 31.10.2018 13:15

@ Md.RayhanKhan, я добавил свой ответ ниже с просмотром вывода. может быть это вам поможет :)

er-sho 01.11.2018 12:56
1
8
975
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы не можете напрямую десериализовать свой ответ API с помощью 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());

Вместо объявления RootClass как List используйте:

var RootClass = await response.Content.ReadAsAsync()

Поместите точку останова в строку и проверьте Тип, возвращаемый API. Поскольку var примет все, что угодно, вы можете проверить ответ. В основном ваша ошибка говорит о том, что вы пытаетесь выполнить CAST к недопустимому типу, поэтому десериализация не работает должным образом.

Кажется, что возвращаемый объект - это массив, возможно, вам нужно получить массив и преобразовать его в список, или даже это совершенно другой объект, чем тот, который вы ожидаете, иметь другие свойства и т. д.

Лучший способ решить -> Выполните отладку и убедитесь, что вы используете правильный тип для десериализации.

"Content.ReadAsAsync>" почему ">" я думаю, это опечатка.

Mihir Dave 31.10.2018 13:10

вы все еще пытаетесь преобразовать его в List <StudentInfo> (в параметре Generic для ReadAsAsync) ... К сожалению, я не могу запустить здесь ваш код, но я почти уверен, что это ваша ошибка - недопустимое приведение. Попробуйте использовать объектное чтение или перегрузку без универсального ReadAsAsync.

Felipe Torres 31.10.2018 14:06

Вы также можете использовать POSTMAN для проверки возврата этого API, а затем соответствующим образом настроить код своих классов.

Felipe Torres 31.10.2018 14:10
Ответ принят как подходящий

Итак, у вас есть класс RootClass. И у вас есть класс под названием StudentInfo.

Какой из них вы рассчитываете получить? Кажется, вы получаете что-то совершенно другое. Как я вижу здесь, https://prnt.sc/lcnlho, вы должны создать новый класс (или изменить структуру RootClass), который будет выглядеть следующим образом

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

И вместо десериализации прямо в List вы должны десериализовать этот класс ResponseContainer:

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

p.s. Если вы хотите использовать свой RootClass, вам следует либо переименовать свойство stdinfo в «data», либо добавить атрибут JsonProperty следующим образом:

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

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

1) Используя JObject в Newtonsoft.json.

Введите команду ниже в консоли диспетчера пакетов.

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

Выход:

enter image description here


2) Без использования Newtonsoft.json.

Введите команду ниже в консоли диспетчера пакетов.

Install-Package Microsoft.AspNet.WebApi.Client

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

    List<StudentInfo> studentInfos = rootClass.data;
}

Выход:

enter image description here

Так что ваши занятия будут

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, возвращающие списки объектов, заключают список в объект верхнего уровня. Например, предположим, что у вас есть тип данных Person в вашем API. Если вы ПОЛУЧИТЕ одного человека, вы можете получить следующий ответ 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;}

}

оставьте свой класс ученика, добавьте учеников моего класса и десериализуйте его;

Другие вопросы по теме