2013-09-10 53 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'訪問器將導致堆棧溢出。你應該在這些'get' /'set'方法中使用真正的後臺字段。另外,getter返回的值不同於setter中設置的值。因此,更好的想法是使這些屬性像所有其他屬性一樣自動實現,並創建返回「已處理」值的單獨只讀屬性(即'get'-only)屬性。這樣你可以序列化,反序列化和序列化對象,它會有正確的值。 – Groo

+0

@格羅,我沒有關注你,你能發表一個鏈接到一些例子嗎? – MB34

回答

2

你的服務器返回一個數組。剛剛嘗試

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

修改了一切,但數據顯示課程爲空。 – MB34

+0

@ MB34我更新了答案,讓我們再來一次。 (在不知道* real * json的情況下很難嘗試盲目幫忙) – I4V

1

請注意,這不是一個答案,原來的問題,但我爲了解釋上述的一些實際的代碼我的評論添加它像一個答案。

與您的代碼第一個問題是FormalDateAgendaUrl性質根本行不通。訪問它們將導致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); } 
    } 
} 

此外,屬性獲取器返回的值不同於通過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