Why is the Json.NET Parser automatically localizin

2020-04-29 02:09发布

问题:

I'm running into problems with the Json.NET Parser. According to the documentation, simply using ToString() with no special converters should leave the Json unaltered.

My Json string, however, is getting modified is having its date automatically localized, and it's causing all sorts of problems for me. For example, when I feed it the following string:

{
    "_type": "Basic",
    "id": "44902a0f-7842-3a2d-83bf-a874ce0b47a1",
    "description": "TestBasicDescription",
    "participation": 1.000000000000000,
    "inception_date": "2014-02-06T20:34:00.925000+00:00",
    "expiry_date": "0001-01-01T00:00:00+00:00"
}

I expect the code

Newtonsoft.Json.Linq.JObject.Parse(content).ToString(Formatting.None);

to produce a string that is virtually identical. What I get, however, is this:

{
    "_type": "Basic",
    "id": "44902a0f-7842-3a2d-83bf-a874ce0b47a1",
    "description": "TestBasicDescription",
    "participation": 1.0,
    "inception_date": "2014-02-06T16:34:00.925-04:00",
    "expiry_date": "0001-01-01T20:00:00-04:00"
}

As you can see, my dates have been localized.

What makes this even worse is that in the case of a boundary date (like DateTime.MinValue as illustrated above) this automatically localized value is actually wrong. The timezone offset has caused the hour value to wrap around, and since the date cannot go any lower, it doesn't change, effectively turning the date into DateTime.MinValue plus 1 day: when it's converted back to UTC time (as it was originally) the date becomes "0001-01-02T00:00:00+00:00". Cue unit tests blowing up.

Why isn't Json.Net behaving like it says it should? Is there any way to just parse the input Json then ToString() it exactly as it was?

回答1:

Wait @JonSkeet! Come back and undelete your answer!

The relevant serializer setting was this: DateParseHandling = Newtonsoft.Json.DateParseHandling.None (which you mentioned), I just didn't know how to apply it in this scenario until @L.B. mentioned the JsonConverter.

This solved the problem.

Newtonsoft.Json.JsonConvert.DeserializeObject(content, 
    new Newtonsoft.Json.JsonSerializerSettings() { 
    DateParseHandling = Newtonsoft.Json.DateParseHandling.None }).ToString();

Giving me back: "expiry_date": "0001-01-01T00:00:00+00:00". Still awfully suspicious that the default behaviour is to mess with your shit, but there you go :)