问题
I have looked at a lot of related questions but none of them seem to be working for me.
I'm trying to serialize 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, the DateTimeOffset
properties are not converted at all. The DateTime
is, but the timezone is indicated using Z
whereas I'm trying to use +00:00
.
回答1:
In your code, you are doing the following:
- Serializing an instance of
Class2
to a JSON string using specificDateTime
-related serialization settings. - Deserializing to a
JToken
hierarchy without using those settings. - (Making additional modifications to the hierarchy - not shown.)
- Serializing the
JToken
hierarchy to a final string (viajson.ToString()
) again without using those settings.
When you do, formatting settings for dates chosen in step #1 get lost.
To solve this, you need to apply the settings every time you serialize from or to a JSON string representation, since, as explained in this documentation page, JSON does not have an "official" format for dates. Because of this, Json.NET applies heuristics for recognizing and formatting dates whenever it converts from and to a JSON string representation - which you are doing not once but thrice.
You could accomplish this by doing:
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 improve efficiency, you could use JToken.FromObject() (or JObject.FromObject() if you prefer) to generate the JToken
hierarchy without needing to create and parse an initial 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 will output a UTC DateTime
in the format "0047-06-20T15:00:00Z"
rather than "2016-06-19T15:00:00+00:00"
for reasons explained here. If you need your UTC DateTime
properties to be serialized in DateTimeOffset
format you might need to use a custom converter.
来源:https://stackoverflow.com/questions/44426207/json-net-messes-up-timezones-for-datetimeoffset-when-serializing