10

We want to show some JSON to a user who is testing our application. So we call our REST service in the ASP.NET code behind file and return a string, which holds a lot of JSON.

We then put it in a PRE element in the page, call beautify to create nice readable JSON and all is good: sort of human readable content is shown.

Good but for one thing: all the dates are shown in the normal JSON format like this "/Date(1319266795390+0800)/"

What I want to do is replace those JSON dates with 'normal' dates, in the JSON (C#) string, so in the code behind that is, before I add the string to the PRE element.

I was thinking about some regex, but i couldn't figure out how...

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
Michel
  • 23,085
  • 46
  • 152
  • 242
  • 1
    Could you include in the text of your question more full example of the JSON string which you want to make more "readable". The problem is that JSON will be used mostly to convert objects to string to be able to transfer to the web client and convert the JSON back to JavaScript object. JavaScript objects should be not readable. If you has for example Array of objects having Date as one from it's properties you can't make it good readable for a human. So it's important to understand which kind of data (which object) you have serialized to JSON string. – Oleg May 07 '12 at 13:53
  • Would you consider a JavaScript solution, or are you dead set on using C# to do conversions? – jamesmortensen May 10 '12 at 02:36

9 Answers9

15

I'v been dealing with dates in JSON string for some time now, there's no standard way for that and which is why there are so many different ways to do it! Maybe it was better if JSON specification could specify an standard format for dates in the first place!

Microsoft is doing it in its own way, counting the msecs since 1970 in UTC format this is something like "/Date(1319266795390+0800)/"

We've been changing the above string to ISO-8601 format ever since using Regular Expressions on top of ASP.Net JavaScriptSerializer output. It is a W3C standard, human readable and the way most browsers serialize Date to string, here's how:

static readonly long DATE1970_TICKS = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
static readonly Regex DATE_SERIALIZATION_REGEX = new Regex(@"\\/Date\((?<ticks>-?\d+)\)\\/", RegexOptions.Compiled);

static string ISO8601Serialization(string input)
{
    return DATE_SERIALIZATION_REGEX.Replace(input, match =>
    {
        var ticks = long.Parse(match.Groups["ticks"].Value) * 10000;
        return new DateTime(ticks + DATE1970_TICKS).ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss.fff");
    });
}

You can easily change the format to satisfy your needs, to see custom Date and Time formats check out MSDN article here

Here's how it's used:

JavaScriptSerializer ser = new JavaScriptSerializer();
var JsonSrt = ISO8601Serialization(ser.Serialize(DateTime.Now));    // "\"2012-05-09T14:51:38.333\""

Update:

There's an alternative to tweak the JSON string returned from the server in JavaScript to more readable form using Regex:

var str = "/Date(1319266795390+0800)/";
str.replace(/\/Date\((\d+)\+\d+\)\//, function (str, date) {
    return new Date(Number(date)).toString();
});
Community
  • 1
  • 1
Kamyar Nazeri
  • 25,786
  • 15
  • 50
  • 87
  • Nice solution. We are using the WCF framework which automaticly converts the objects to JSON. In code, we just return a POCO object annotated with datamember attributes, and when the function is called, due to the nature of the project type i think, the output is converted to JSON. What i want to say is that (as far as i know) there is no moment / place in code where i can kick in with the custom data replace code – Michel May 14 '12 at 09:51
  • WCF makes use of `DataContractJsonSerializer` to serialize POCO/DataContract objects, you can tweak default JSON serializer, and replace the `DataContractJsonSerializer` with a custom one! Here's a post to show you how: http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx Anyhow, there's an alternative to tweak the JSON text returned from server using Regex in JavaScript as I'll show in an update above – Kamyar Nazeri May 14 '12 at 15:46
  • This works great for Date(##) but not Date(##+####) i.e. does not contain any timezone information. Trying to do this on this string: "{\"EndTime\":\"\\/Date(1381479678557)\\/\",\"StartTime\":\"\\/Date(1381479678557+0200)\\/\"}". And it only replaces the EndTime and not the StartTime – JensB Oct 11 '13 at 08:23
5

The solution is within the string shown in the question. The JavaScript Date object will parse that format and produce a readable version so Date(1319266795390+0800) returns "Wed Apr 18 2012 08:13:22 GMT-0500 (Central Daylight Time)".

To remove the forward slash from the string you could use the replace function with a regular expression: "/Date(1319266795390+0800)/".replace(/\//g, '').

Anna Brenden
  • 3,837
  • 2
  • 21
  • 19
  • Ah, but my string contains much more than just that date, it contains 50 other person properties amongst which a few dates. – Michel Apr 18 '12 at 14:17
  • Michel - Regular expressions are by nature intended to retrieve specific data from very long strings. What Eric is suggesting should work for you can can be done entirely with JavaScript. – jamesmortensen May 10 '12 at 02:24
4

You can use this:

string date = "/Date(1319266795390+0800)/";
string regex = @"/Date\((.*?)\+(.*?)\)/";
Match match = Regex.Match(date, regex);
DateTime d = new DateTime(1970, 01, 01).AddMilliseconds(long.Parse(match.Result("$1")));
jeremy
  • 904
  • 7
  • 15
2

suppose the class you want to serialize looks like this:

public class Something
{
    public int ID;
    public string Name;
    public DateTime Date;
}

change it to:

public class Something
    {
        public int ID;
        public string Name;
        public DateTime Date;
        public string HumanReadableDate { get { return Date.ToLongDateString(); } }
    }

or, if you want that extra property to display only in test enviroment:

public class Something
    {
        public int ID;
        public string Name;
        public DateTime Date;
        #if DEBUG
        public string HumanReadableDate { get { return Date.ToLongDateString(); } }
        #endif
    }

also, instead of .ToLongDateString() you can use .ToString("yyyy-MM-dd HH:mm") or any other format

y34h
  • 1,631
  • 1
  • 11
  • 17
1

Use as regex something like:

(?<= /Date\( ) 
  (?<ticks>[0-9]+)
  ((?<zonesign>[+-])
   (?<zonehour>[0-9]{2})
   (?<zoneminutes>[0-9]{2})
  )?
(?= \)/ )

This will match the part inside the parentheses of /Date(1319266795390+0800)/. You can then call Regex.Replace on the whole JSON string to replace the numbers with a nicely formatted DateTime:

Use the Match object you get in the match evaluator delegate and extract the ticks, zonesign, zonehour and zoneminutes part, convert it to integers.

Then convert the javascript ticks to .NET ticks (should be *10000), construct the .NET DateTime out of ticks and add/substract the hours and minutes for the time zone. Convert the DateTime to a string and return it as the replacement.

Markus Meyer
  • 173
  • 1
  • 6
  • 14
1

If your JSON is a serialised representation of a .NET class, maybe you could use the DataContractJsonSerializer to deserialise it on the server, or perhaps you could just define a stub class for your JSON object if you don't need a generic solution to handle multiple datasets:

string json = "{\"Test\": \"This is the content\"}";
DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(TestJson));
var deserialisedContent = ds.ReadObject(new MemoryStream(Encoding.ASCII.GetBytes(json)));

foreach (var field in typeof (TestJson).GetFields())
{
    Console.WriteLine("{0}:{1}", field.Name, field.GetValue(deserialisedContent));
}

...

[DataContract]
private class TestJson
{
    [DataMember]
    public string Test;
}
Simon MᶜKenzie
  • 8,344
  • 13
  • 50
  • 77
1

Use Newtonsoft.JSON. You can provide your own serializers per type, and serialize dates however you want.

http://james.newtonking.com/projects/json-net.aspx

Thinking Sites
  • 3,494
  • 17
  • 30
1

Make a string property for example dateofbirth I am defining here, and return your datetime variable as:

    public string DateOfBirthString
    {
        get { return DateOfBirth.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss"); }
        set { DateOfBirth = string.IsNullOrEmpty(value) ? new DateTime(1900, 1, 1) : Convert.ToDateTime(value); }
    }

because this will return string so it will be same at client side so and aslo take string dateTime from user and convert it.

Zaheer Ahmed
  • 28,160
  • 11
  • 74
  • 110
0
string input = [yourjsonstring]; 
MatchEvaluator me = new MatchEvaluator(MTListServicePage.MatchDate);
string json = Regex.Replace(input, "\\\\/\\Date[(](-?\\d+)[)]\\\\/", me, RegexOptions.None)
user1040975
  • 420
  • 5
  • 16