Skip to content
This repository has been archived by the owner on Jan 24, 2021. It is now read-only.

JavaScriptSerializer not working with TimeSpan #336

Closed
jakejscott opened this issue Oct 6, 2011 · 4 comments
Closed

JavaScriptSerializer not working with TimeSpan #336

jakejscott opened this issue Oct 6, 2011 · 4 comments
Assignees
Milestone

Comments

@jakejscott
Copy link
Contributor

Hi Guys,

Seems to serialise okay:
{"Ticks":12096000000000,"Days":14,"Hours":0,"Milliseconds":0,"Minutes":0,"Seconds":0,"TotalDays":14,"TotalHours":336,"TotalMilliseconds":1209600000,"TotalMinutes":20160,"TotalSeconds":1209600}

But when I deserialize I am getting an empty time span :(

public class NancyJsSerialiserTest
{
    [Fact] 
    public void Should_be_able_to_serialise_and_deserialise_timespan()
    {
        var serializer = new JavaScriptSerializer();
        var sb = new StringBuilder();
        var days = TimeSpan.FromDays(14);

        serializer.Serialize(days, sb);
        Console.WriteLine(sb.ToString());

        var actual = serializer.Deserialize<TimeSpan>(sb.ToString());

        actual.ShouldEqual(days);
    }
}
@grumpydev
Copy link
Member

This is a limitation of the Microsoft one too (JSON doesn't really do times/dates), but we can "fix" it by registering a converter:

namespace JSONTestingAgain
{
    using System;
    using System.Collections.Generic;

    using Nancy.Json;

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

Then:

serializer.RegisterConverters(new[] { new TimeSpanJsonConverter() });

It may be worth discovering / adding a static collection to allow users to add converters, and also ship some (like this one) in the box.

@ghost ghost assigned grumpydev Oct 8, 2011
@grumpydev
Copy link
Member

Restructured the JSON namespaces slightly so now the configuration is in the Json namespace (rather than responses) and now has an extra IList property for registering converters which is used in both JsonResponse and the JSON body deserializer.

grumpydev added a commit to grumpydev/Nancy that referenced this issue Oct 8, 2011
Moved JSONSettings to the JSON namespace, added a
new converter property and a default TimeSpan
converter.
@jakejscott
Copy link
Contributor Author

Legend! Thanks :)

@grumpydev
Copy link
Member

No worries .. it'll be in 0.8.1 this week.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants