Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper Way to Convert JSON Date to .NET DateTime During Deserialization

I have a javascript function that calls an MVC controller with JSON data:

var specsAsJson = JSON.stringify(specs);
$.post('/Home/Save', { jsonData: specsAsJson });

On the server side, within the controller, I can't seem to get past this error:

/Date(1347992529530)/ is not a valid value for DateTime.

That exception happens when I call Deserialize() (third line in method below):

    public ActionResult Save(string jsonData)
    {
        var serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new[] { new TimeSpanJsonConverter() });
        var specs = serializer.Deserialize<List<EquipmentSpecWithParameterlessConstructor>>(jsonData);

        return View("Index", _allTrackerJobs);
    }

I've been doing some googling, and the above code is my latest attempt to make this work (using the TimeSpanJsonConverter from here). Other approaches show sending only a date to the server, but I have a list of objects that have dates as some properties.

Is there an elegant, generally-accepted approach to solving this, or do we still need some kind of ugly work-around? What's the right way to resolve this?

=================== End of original question ===================


Edit - SOLVED by serializing using JsonConvert

See my answer below (not the crappy work-around in this question).


Edit - Crappy work-around

I created a DTO with the exact same fields as the domain object, except that I made the date fields strings so they would deserialize. Now that I can deserialize it, I'll work on getting the dates into a valid format so I can create domain objects from my DTOs.

public class EquipmentSpecDto
{
    public string StartTime { get; set; }
    public string EndTime { get; set; }
    // more properties here
}

And I simply just used the DTO for the deserialization:

var specs = serializer.Deserialize<List<EquipmentSpecDto>>(jsonData);

Edit 2 - Converting JavaScript Dates to .NET

For completeness, and in the hopes that I save someone else an hour, this is how I was able to convert the javascript dates:

    foreach (EquipmentSpecDto specDto in specDtos)
    {
        // JavaScript uses the unix epoch of 1/1/1970. Note, it's important to call ToLocalTime()
        // after doing the time conversion, otherwise we'd have to deal with daylight savings hooey.
        DateTime unixEpoch       = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        Double startMilliseconds = Convert.ToDouble(specDto.StartTime.Substring(6, 13));
        Double endMilliseconds   = Convert.ToDouble(specDto.EndTime.Substring(6, 13));
        DateTime startTime       = unixEpoch.AddMilliseconds(startMilliseconds).ToLocalTime();
        DateTime endTime         = unixEpoch.AddMilliseconds(endMilliseconds).ToLocalTime();
        EquipmentSpec spec       = new EquipmentSpec(startTime, endTime, specDto.Equipment);

        specs.Add(spec);
    }
like image 558
Bob Horn Avatar asked Sep 18 '12 18:09

Bob Horn


People also ask

How should JSON store date value?

JSON does not have a built-in type for date/time values. The general consensus is to store the date/time value as a string in ISO 8601 format.

Does JSON Stringify convert date to UTC?

Using default JS. JSON. stringify converts date to UTC format which means we are losing information about client offset.

Does JSON accept DateTime?

Json library parses and writes DateTime and DateTimeOffset values according to the ISO 8601-1:2019 extended profile.

How do I deserialize a JSON file?

A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.


2 Answers

I found a simple answer. In my javascript, I was serializing the data using the JavaScriptSerializer. After much googling, I found this article that shows how to serialize using JsonConvert that causes a more .NET-friendly DateTime to be used.

Old:

var specs = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ViewBag.JobSpecEquipment))

Dates look like this: Date(1348017917565)

New:

var specs = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.JobSpecEquipment));

Dates look like this: 2012-09-18T21:27:31.1285861-04:00

So the problem was really how I was serializing in the first place. Once I used JsonConvert, deserialization on the back end simply worked.

like image 73
Bob Horn Avatar answered Oct 07 '22 21:10

Bob Horn


I found this piece of code on the internet. It worked like a charm for me...

function customJSONstringify(obj) {
    return JSON.stringify(obj).replace(/\/Date/g, "\\\/Date").replace(/\)\//g, "\)\\\/")
}
like image 26
Wagner Bertolini Junior Avatar answered Oct 07 '22 19:10

Wagner Bertolini Junior