JavaScriptSerializer не десериализует DateTime / TimeSpan должным образом - PullRequest
1 голос
/ 08 декабря 2010

Возникла проблема, когда DateTime / TimeSpan, кажется, не десериализуются должным образом с JavaScriptSerializer. Когда я возвращаю Объект после десериализации, TimeSpan становится пустым, а если я использую DateTime, тогда все время не в порядке. Нашел эту статью, но она мне особо не помогла. http://www.west -wind.com / блог / ShowPost.aspx? ID = 471402

У кого-нибудь есть идеи? Должен ли я попробовать библиотеку 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;
    }

Ответы [ 2 ]

3 голосов
/ 04 сентября 2012

Я нашел ответ в следующем посте на GitHub:

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

По сути, ответом было создание нового TimeSpanJsonConverter, который наследуется от JavaScriptConverter, а затем передатьк экземпляру вашего класса сериализатора:

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

Полный класс для справки (записано 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;
    }
}
0 голосов
/ 15 декабря 2010

Это исправит вашу проблему, если у вас возникнет такая же проблема.

http://blog.devarchive.net/2008/02/serializing-datetime-values-using.html

Все объекты DateTime должны быть явно указаны как UTC.

...