2013-09-10 5 views
0

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

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

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

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 double 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\">Agenda</a>"); 
      } 
      else 
      { 
       val = "Agenda"; 
      } 
      return val; 
     } 

    } 


} 
+0

Вы должны размещать фактические данные, полученные от веб-службы. Установите точку останова в строке, где вы собираетесь десериализовать и опубликовать фактическое содержимое 'returnjson'. – Groo

+0

Кстати, это выглядит так: «FormalDate» и «AgendaURL» Accessors вызовут переполнение стека. Вы должны использовать реальные поля поддержки в этих методах 'get' /' set'. Кроме того, для геттера нередко возвращается другое значение, чем одно заданное через сеттер. Таким образом, даже лучшая идея заключалась бы в том, чтобы эти свойства были автоматически реализованы, как и все остальные, и создавали отдельные свойства только для чтения (т. Е. 'Get'-only), которые возвращают« обработанные »значения. Таким образом, вы можете сериализовать, десериализовать и сериализовать снова объект, и он будет иметь правильные значения. – Groo

+0

@Groo, я не буду следовать за вами, можете ли вы опубликовать ссылку на некоторые примеры? – MB34

ответ

2

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

Course[] courses = JsonConvert.DeserializeObject<Course[]>(returnjson); 
+0

Изменено все, но данные показывают, что Курсы будут нулевыми. – MB34

+0

@ MB34 Я обновил ответ. Давайте дадим еще один снимок. (Трудно попытаться помочь вслепую, не зная * настоящего * json) – I4V

1

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

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

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

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); 
     } 
    } 
} 
+0

Спасибо за объяснение. Похоже, у меня есть еще кое-что научиться делать с C#. Я исхожу из базы Delphi и PHP, и вы можете сделать это в обоих. – MB34

Смежные вопросы