Json.Net triggers time slots for DateTimeOffset on serialization
I've looked at a lot of related questions, but none of them seem to work for me.
I am trying to arrange everything in UTC. Here's my code:
class Class1
{
static void Main()
{
Class2 foo = new Class2();
JObject json = JObject.Parse(JsonConvert.SerializeObject(foo, new JsonSerializerSettings()
{
DateParseHandling = DateParseHandling.DateTimeOffset,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateTimeZoneHandling = DateTimeZoneHandling.Utc
}));
Console.WriteLine(json.ToString());
Console.Read();
}
}
class Class2
{
public DateTimeOffset time = new DateTimeOffset(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(14663484000000000));
public DateTimeOffset time2 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(14663484000000000);
public DateTime time3 = new DateTime(14663484000000000);
}
Here's the output:
{
"time": "2016-06-19T08:00:00-07:00",
"time2": "2016-06-19T08:00:00-07:00",
"time3": "0047-06-20T15:00:00Z"
}
Here's the output I'm trying to get:
{
"time": "2016-06-19T15:00:00+00:00",
"time2": "2016-06-19T15:00:00+00:00",
"time3": "0047-06-20T15:00:00+00:00"
}
As you can see, properties DateTimeOffset
are not converted at all. DateTime
is, but the timezone is specified with Z
, whereas I am trying to use +00:00
.
source to share
In your code, you do the following:
- Serialize an instance
Class2
for a JSON string using specific serialization settingsDateTime
. - Removing deserialization into the hierarchy
JToken
without using these parameters. - (Additional changes to the hierarchy are not shown.)
- Re-serialize the hierarchy
JToken
to the last line (throughjson.ToString()
) without using these settings.
When you do this, the formatting options for the dates you selected in step 1 will be lost.
To solve this problem, you need to apply the settings every time you serialize a string or to a JSON string representation, since, as described in this documentation page, JSON has no "official" format for dates. Because of this, Json.NET applies heuristics to recognize and format dates whenever it converts from and to a JSON string representation, which you do not once, but three times.
You can accomplish this by running:
var settings = new JsonSerializerSettings()
{
DateParseHandling = DateParseHandling.DateTimeOffset,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateTimeZoneHandling = DateTimeZoneHandling.Utc
};
// Generate initial serialization
var initialString = JsonConvert.SerializeObject(foo, settings);
// Parse back to JToken
var json = JsonConvert.DeserializeObject<JObject>(initialString, settings);
// Make modifications as required
// json["foo"] = "bar";
// Generate final JSON.
var finalString = JsonConvert.SerializeObject(json, Formatting.Indented, settings);
To be more efficient, you can use JToken.FromObject()
(or JObject.FromObject()
if you like) to generate the hierarchy JToken
without having to create and parse the original string representation:
var settings = new JsonSerializerSettings()
{
DateParseHandling = DateParseHandling.DateTimeOffset,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateTimeZoneHandling = DateTimeZoneHandling.Utc
};
var json = JToken.FromObject(foo, JsonSerializer.CreateDefault(settings));
// Make modifications as required
// json["foo"] = "bar";
// Generate final JSON.
var finalString = JsonConvert.SerializeObject(json, Formatting.Indented, settings);
Note, however, that Json.NET outputs UTC DateTime
in format "0047-06-20T15:00:00Z"
, not "2016-06-19T15:00:00+00:00"
for the reasons described here here . If you need your UTC DateTime
properties to be serialized in the format DateTimeOffset
, you may need a custom converter .
source to share