2010-12-08 5 views
1

Problème lié à la date à laquelle DateTime/TimeSpan ne semble pas correctement désérialisé avec JavaScriptSerializer. Lorsque je récupère l'objet après la désérialisation, le TimeSpan est vide et si j'utilise DateTime, les heures sont toutes déformées. J'ai trouvé cet article mais ça ne m'a pas vraiment aidé. http://www.west-wind.com/weblog/ShowPost.aspx?id=471402JavaScriptSerializer ne désérialisant pas correctement DateTime/TimeSpan

Vous avez des idées? Devrais-je peut-être essayer la bibliothèque json.net?

public class JsonFilter : ActionFilterAttribute 
{ 
    public string Param { get; set; } 
    public Type JsonDataType { get; set; } 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) 
     { 
      string inputContent; 
      using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) 
      { 
       inputContent = sr.ReadToEnd(); 
      } 

      JavaScriptSerializer serializer = new JavaScriptSerializer(); 
      var result = serializer.Deserialize(inputContent, JsonDataType); 
      filterContext.ActionParameters[Param] = result; 
     } 
    } 
} 

public class RosterItem 
{ 
    public RosterItem() 
    { 
     comments = new List<Form.Comment>(); 
    } 
    public Boolean dirty { get; set; } 
    public int id { get; set; } 
    public int staffId { get; set; } 
    public String description { get; set; } 
    public int activityId { get; set; } 
    public DateTime date { get; set; } 
    public TimeSpan startTime { get; set; } 
    public TimeSpan endTime { get; set; } 
    public List<Form.Comment> comments { get; set; } 
} 

    [JsonFilter(Param = "rosterItem", JsonDataType = typeof(RosterItem))] 
    public int SaveRosterEntry(RosterItem rosterItem) 
    { 
     RosterEntry rosterEntry = rosterEntryRepository.GetRosterEntry(rosterItem.id); 
     if (rosterEntry == null) 
     { 
      rosterEntry = new RosterEntry(); 
      rosterEntryRepository.Add(rosterEntry); 
     } 
     rosterEntry.ActivityID = rosterItem.activityId; 
     rosterEntry.StartTime = rosterItem.startTime; 
     rosterEntry.EndTime = rosterItem.endTime; 
     rosterEntry.RosterDate = rosterItem.date; 
     rosterEntry.RosterEmployeeID = rosterItem.staffId;    
     rosterEntryRepository.Save(); 
     return rosterEntry.RosterEntryID; 
    } 

Répondre

2

Je trouve la réponse dans le post suivant sur GitHub:

https://github.com/NancyFx/Nancy/issues/336

Fondamentalement, la réponse était de créer une nouvelle TimeSpanJsonConverter qui hérite de JavaScriptConverter et ensuite passer que à une instance de votre classe sérialiseur:

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer() 
serializer.RegisterConverters(new[] { new TimeSpanJsonConverter() }); 

La classe complète de référence est (écrit par GrumpyDev):

public class TimeSpanJsonConverter : JavaScriptConverter 
{ 
    public override IEnumerable<Type> SupportedTypes 
    { 
     get 
     { 
      return new[] { typeof(TimeSpan) }; 
     } 
    } 

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     return new TimeSpan(
      this.GetValue(dictionary, "days"), 
      this.GetValue(dictionary, "hours"), 
      this.GetValue(dictionary, "minutes"), 
      this.GetValue(dictionary, "seconds"), 
      this.GetValue(dictionary, "milliseconds")); 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     var timeSpan = (TimeSpan)obj; 

     var result = new Dictionary<string, object> 
      { 
       { "days", timeSpan.Days }, 
       { "hours", timeSpan.Hours }, 
       { "minutes", timeSpan.Minutes }, 
       { "seconds", timeSpan.Seconds }, 
       { "milliseconds", timeSpan.Milliseconds } 
      }; 

     return result; 
    } 

    private int GetValue(IDictionary<string, object> dictionary, string key) 
    { 
     const int DefaultValue = 0; 

     object value; 
     if (!dictionary.TryGetValue(key, out value)) 
     { 
      return DefaultValue; 
     } 

     if (value is int) 
     { 
      return (int)value; 
     } 

     var valueString = value as string; 
     if (valueString == null) 
     { 
      return DefaultValue; 
     } 

     int returnValue; 
     return !int.TryParse(valueString, out returnValue) ? DefaultValue : returnValue; 
    } 
} 
+1

La solution est idéale pour résoudre la sérialisation TimeSpan, mais je pense que ce problème est lié à DateTime. –