18

Is there anyway to change the default JSON serialization/deserialization of DateTime in WCF?

Currently, DateTime are serialized into the /Date(1372252162657+0200)/ format, which should've been fine but I'm running into issues when my server is not in UTC (which I can't change).

All date/time data that is being processed by this service is in UTC format. Everything works when the server is in UTC. However, the staging/prod environments are set to GMT+1(Paris) and the serializer is assuming that the dates/times are in GMT+1, completely ignoring the attribute Kind. So as you'd expect calling DateTime.SetKind() and setting it to UTC will not work. In effect, the serialized times are delayed by an hour.

I can either do two-way date conversations (it also makes the same assumption when deserializing so its always GMT+1) conversation of dates: UTC to/from server time, but this is to tedious. So I thought maybe I could just override the default serialization behavior.

Mel
  • 3,058
  • 4
  • 26
  • 40

5 Answers5

24

Just to expand on tdelepine's code snippet, here the code I've used:

In my WCF JSON Service, I had a (nullable) DateTime value, and wanted my service to return the date in a more readable format, so my iPhone app would be able to interpret it.

Here's what my JSON looked like, after applying a few changes:

enter image description here

Notice the UpdateDateOriginal field, which is the default way that WCF writes DateTimes, and the friendlier UpdateDate field, which I created using the code below.

My original lines looked like this:

[DataMember]
public DateTime? UpdateDateOriginal { get; set; }

... and here are the lines to create the new friendlier UpdateDate JSON value.

[IgnoreDataMember]
public DateTime? UpdateDate { get; set; }

[DataMember(Name = "UpdateDate")]
private string UpdateDateString { get; set; }

[OnSerializing]
void OnSerializing(StreamingContext context)
{
    if (this.UpdateDate == null)
    this.UpdateDateString = "";
    else
    this.UpdateDateString = this.UpdateDate.Value.ToString("MMM/dd/yyyy HH:mm", CultureInfo.InvariantCulture);
}

[OnDeserialized]
void OnDeserializing(StreamingContext context)
{
    if (this.UpdateDateString == null)
    this.UpdateDate = null;
    else
    this.UpdateDate = DateTime.ParseExact(this.UpdateDateString, "MMM/dd/yyyy HH:mm", CultureInfo.InvariantCulture);
}

Actually, you may find it more useful to return DateTime values in ISO8601 format. For example:

UpdateTime: "2014-08-24T13:02:32",

To do this, simply use my code above, but change the string "MMM/dd/yyyy HH:mm" to "s" in both places.

And, if your DateTime values are stored in UTC, but you wanted your WCF services to return the values in the user's local timezone, you can follow my tips here:

Get DateTime in users local timezone

Isn't life easier, with a few simple examples !

Community
  • 1
  • 1
Mike Gledhill
  • 27,846
  • 7
  • 149
  • 159
  • I need `2018-02-06T14:40:43.511Z` ***DateTime format*** – Kiquenet Feb 23 '18 at 10:42
  • 1
    I *think* you need to use: ToString("yyyy-MM-ddTHH:mm:ssK") Some articles are saying that the "Z" part means it's UTC, and you're trying to include that in the string. – Mike Gledhill Feb 23 '18 at 11:09
  • I think that should be `yyyy-MM-ddTHH:mm:ss.fffK` or just `o`. – NetMage Jan 31 '19 at 01:02
  • This is the best answer. Clean simple, and straight forward. – Hasan Shouman Apr 05 '21 at 16:20
  • 1
    dateTime.ToString("O") is how I get ISO 8601 compliant dates from .NET: https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings#the-round-trip-o-o-format-specifier – Jacob McKay Apr 30 '21 at 20:42
13

you can use this workaround, In your json object definition

[IgnoreDataMember]
public DateTime dateObject;

public string dateCustomSerialize
{
 get {
//Custom get
}
set {
//Custom set
}
}

In assessor place your custom format serialisation

tdelepine
  • 1,986
  • 1
  • 13
  • 19
4

Yes, this can be done using the concept called "Message Formatters"

But Message Formatter would be tough and out of scope to explain here on stack overflow. You can refere WCF Extensibility : Message Formatters

If you don't want mess up with this then an hack is available.

Set the return type of each method to Stream.

e.g.

        public Stream GetStaticData()
        {
            var objTobeReturned = something;
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
            return new MemoryStream(Encoding.UTF8.GetBytes(objTobeReturned.ToJson()));
        }

here ToJson() is my own extension method which converts object into json string using NewtonSoft library.

WCF will skip the stream output for serializing and will pass it to your client as it is.

I hope you got your answer.

Community
  • 1
  • 1
Ronak Patel
  • 2,570
  • 17
  • 20
1

This does not solve your issue of timezones, but I'll post it here for others who are battling it out with WCF, ticks and DateTime.

If you don't want ticks, but human-readable time format, you can do it by introducing an additional string property. Then it's a matter of fiddling with the DateTime before turning the value into a string.

    [IgnoreDataMember]    // Ignore the original tick date.
    public DateTime LastReminderDate { get { return _lastReminderDate; } set { _lastReminderDate = value; } }
    [DataMember]          // Make sure you have a public or private setter!
    public string LastReminderDateText { get { return _lastReminderDate.ToString(); } set { _lastReminderDate = DateTime.Parse(value); } }
Robotronx
  • 1,728
  • 2
  • 21
  • 43
0

One way is to use a message formatter to change the default DataContractSerializer as described in WCF Extensibility – Message Formatters.

Another option is to write an extension method that loads your object into a stream and then you can apply whatever serializer you want to the object. See the accepted answer for Replace default JSON serializer in WCF 4 to JSON.NET for details on how to do this.

Community
  • 1
  • 1
Karl Anderson
  • 34,606
  • 12
  • 65
  • 80
  • ***SERIALIZATION*** `JavaScriptSerializer` ***issues*** with `DateTime` View https://andrearegoli.wordpress.com/2014/09/11/json-serialization-c/ Maybe using `DataContractJsonSerializer, JsonSerializer (ServiceStack) and JsonConvert (json.net)`. Any real world sample? – Kiquenet Feb 23 '18 at 10:44