Разбор JSON в Object

Попытка получить результат вызова webservice для возврата модели. Я получаю ошибку: нельзя десериализовать текущий массив JSON (например, [1,2,3]) в тип 'CI.Models.Schedule', потому что для этого требуется объект JSON (например, {"name": "value"}) для десериализации.

public Schedule getCourseSchedule()
{
 var obj = new
 {
 States = new[] { new { State = "MX" } },
 Zip = "",
 Miles = "",
 PaginationStart = 1,
 PaginationLimit = 3
 };
 using (var client = new WebClient())
 {
 client.Headers[HttpRequestHeader.ContentType] = "apoplication/json";
 var url = "http://192.168.1.198:15014/ShoppingCart2/CourseSchedule";
 var json = JsonConvert.SerializeObject(obj);
 byte[] data = Encoding.UTF8.GetBytes(json);
 byte[] result = client.UploadData(url, data);
 string returnjson = Encoding.UTF8.GetString(result);
 Schedule sched = JsonConvert.DeserializeObject<schedule>(returnjson);
 return sched;
 }
}
</schedule>

Модель расписания:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;

namespace CI.Models
{
 public class Schedule
 {
 public IEnumerable<course> Courses { get; set; }
 }

 public class Course
 {

/*
JSON Data returned from web service: 
{
 "ProgramGroup":"MR",
 "ProgramCode":"RM",
 "EventCode":"20160901MXMR",
 "FormalDate":"September 1-2, 2016",
 "StartDate":"2016\/09\/01",
 "Price":5,
 "LocName":"WB Hotel",
 "LocAddress":"Av. Speedy Gonzales 220",
 "LocCity":"Monterrey",
 "LocState":"MX",
 "LocZipCode":null,
 "LicenseeURL":null,
 "AgendaURL":"NA",
 "SeatsAreAvailable":"2",
 "GeneralInfoHTML":"General Info goes here.",
 "GateKeeperHTML":null,
 "EventType":"SS",
 "TotalCourses":3
}
*/
 public string ProgramGroup { get; set; }
 public string ProgramCode { get; set; }
 public string EventCode { get; set; }
 public string FormalDate { get { return FormalDate; } set { FormalDate = convertFormalDateToSpanish(value); } }
 public string StartDate { get; set; }
 public ****** Price { get; set; }
 public string LocName { get; set; }
 public string LocAddress { get; set; }
 public string LocCity { get ; set; }
 public string LocState { get; set; }
 public string LocZipCode { get; set; }
 public string LicenseeURL { get; set; }
 public string AgendaURL { get { return AgendaURL; } set { AgendaURL = buildAgendaLink(value); } }
 public string SeatsAreAvailable { get; set; }
 public string GeneralInfoHTML { get; set; }
 public string GateKeeperHTML { get; set; }
 public string EventType { get; set; }
 public int TotalCourses { get; set; }

 public string convertFormalDateToSpanish(string val) 
 {
 DateTime TheDate = DateTime.Parse(StartDate);
 string[] FormalDate = val.Split(" ".ToCharArray());
 CultureInfo ci = new CultureInfo("es-ES");
 string _Date = FormalDate[1].Replace("-", " al ").Replace(",", "");
 string _Month = ci.TextInfo.ToTitleCase(TheDate.ToString("MMMM", ci));
 val = string.Concat(_Date, " ", _Month);
 return val;
 }

 private string buildAgendaLink(string val)
 {
 if (val.Trim() != "")
 {
 val = string.Concat("<a href="\" pdfs="" ","="" eventcode,="" "_agenda.pdf\"="" target="_blank">Agenda</a>");
 }
 else
 {
 val = "Agenda";
 }
 return val;
 }

 }


}
</course>
2 ответа

Сервер возвращает массив. Просто попробуй

Course[] courses = JsonConvert.DeserializeObject<course[]>(returnjson);
</course[]>


Обратите внимание, что это не ответ на исходную проблему, но я добавил ее как ответ, чтобы объяснить мой комментарий выше с помощью некоторого фактического кода.

Первая проблема с вашим кодом заключается в том, что свойства FormalDate и AgendaUrl просто не будут работать. Доступ к ним приведет к StackOverflowException, потому что вы в основном определили их рекурсивно.

Свойство - это просто синтаксический сахар для двух отдельных методов getter/setter, поэтому, написав это:

public class Course
{
 public string FormalDate
 {
 get { return FormalDate; }
 }
}

Вы в основном пишете это:

public class Course
{
 public string GetFormalDate()
 {
 // recursive call, with no terminating condition,
 // will infinitely call itself until there is no
 // more stack to store context data (and CLR
 // will then throw an exception)
 return GetFormalDate(); 
 }
}

Чтобы исправить это, вам нужно добавить фактическое поле поддержки, например:

public class Course
{
 private string _formalDate; // <-- this is a backing field;

 // and this property uses the backing field to read/store data
 public string FormalDate 
 { 
 get { return _formalDate; } 
 set { _formalDate = convertFormalDateToSpanish(value); } 
 }
}

Кроме того, необычно для свойства getter возвращать другое значение, чем значение, заданное через setter. Другими словами, я бы никогда не ожидал этого от класса:

var course = new Course();
course.StartDate = "2016/09/01";
course.FormalDate = "September 1-2, 2016";

Console.WriteLine(course.FormalDate); // prints "1 al 2 Septiembre" ?

Я предпочел бы переместить эту функциональность в другой класс или, по крайней мере, создать разные свойства, которые возвращают эти значения:

public class CourseInfo
{
 // this is now a "dumb" auto-implemented property
 // (no need for a backing field anymore)
 public string FormalDate { get; set; }

 // this read-only property returns the converted value
 public string LocalizedFormalDate
 {
 get 
 {
 return convertFormalDateToSpanish(FormalDate);
 }
 }
}

licensed under cc by-sa 3.0 with attribution.