Loading JSON Dates

JSON is a great format for serializing data, but unfortunately it does not support dates.

The Problem

If you serialize an object that contains date fields using JSON.stringify, the dates will be converted to strings. If you then parse the same object back using JSON.parse, they will remain strings.

Note how the "Date" column contains strings in the example below:

Id
Country
Sales
Expenses
Date
0
US
489.51
2,358.24
2017-02-08T12:47:06.405Z
1
Germany
7,803.20
2,513.54
2017-02-09T12:47:06.405Z
2
UK
9,996.58
2,616.71
2017-02-10T12:47:06.405Z
3
Japan
9,351.68
3,030.59
2017-02-10T12:47:06.405Z
4
Spain
349.51
7,358.24
/Date(1486561758556)/

The Solution

The solution for this problem is to use a 'reviver' function in the call to JSON.parse that will inspect the strings and convert those that look like dates into date objects.

Following is a grid showing the same data, this time parsed with a date reviver function:

Id
Country
Sales
Expenses
Date
0
US
489.51
2,358.24
2/8/2017
1
Germany
7,803.20
2,513.54
2/9/2017
2
UK
9,996.58
2,616.71
2/10/2017
3
Japan
9,351.68
3,030.59
2/10/2017
4
Spain
349.51
7,358.24
2/8/2017
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// This file locates: "Scripts/Lesson/C1Mvc/CVLoadingJsonDates.js".
c1.documentReady(function () {
    // start with some data encoded as JSON
    // (as it would arrive from a server)
    var json = '[' +
      '{"id":0,"country":"US","sales":489.51,"expenses":2358.24,"date":"2017-02-08T12:47:06.405Z"},' +
      '{"id":1,"country":"Germany","sales":7803.20,"expenses":2513.54,"date":"2017-02-09T12:47:06.405Z"},' +
      '{"id":2,"country":"UK","sales":9996.58,"expenses":2616.71,"date":"2017-02-10T12:47:06.405Z"},' +
      '{"id":3,"country":"Japan","sales":9351.68,"expenses":3030.59,"date":"2017-02-10T12:47:06.405Z"},' +
      '{"id":4,"country":"Spain","sales":349.51,"expenses":7358.24,"date":"/Date(1486561758556)/"}' +
      ']';
 
    // decode the data
    // no special parsing for dates, the date field will contain strings
    var dataBad = JSON.parse(json);
 
    // show the bad data in a grid
    var theGridBad = wijmo.Control.getControl('#theGridBad');
    theGridBad.itemsSource = dataBad;
 
    // decode the data
    // use with a Date reviver to restore date fields
    var dataGood = JSON.parse(json, function(key, value) {
        if (typeof value === 'string') {
       
            // parse dates saved as JSON-strings
            var m = value.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/);
            if (m) {
                return new Date(Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +m[6]));
            }
 
            // parse dates saved as OData-style strings
            m = value.match(/^\/Date\((\d+)\)\/$/);
            if (m) {
                return new Date(parseInt(m[1]));
            }
        }
        return value; 
    });
 
    // show the good data in a grid
    var theGridGood = wijmo.Control.getControl('#theGridGood');
    theGridGood.itemsSource = dataGood;
});
1
2
3
4
5
6
7
8
9
10
11
12
13
using System.Web.Mvc;
 
namespace LearnMvcClient.Controllers
{
    public partial class C1MvcController : Controller
    {
        // GET: CVLoadingJsonDates
        public ActionResult CVLoadingJsonDates()
        {
            return View();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<h1>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Title)
</h1>
<p>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Text1)
</p>
 
<h3>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Title1)
</h3>
<p>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Text2)
</p>
<p>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Text3)
</p>
@Html.C1().FlexGrid().Id("theGridBad")
 
<h3>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Title2)
</h3>
<p>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Text4)
</p>
<p>
    @Html.Raw(Resources.C1Mvc.CVLoadingJsonDates_Text5)
</p>
@Html.C1().FlexGrid().Id("theGridGood")