为什么 JSON.NET 默认的 DateTime 序列化改变了?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15520717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:10:40  来源:igfitidea点击:

Why has JSON.NET default DateTime serialization changed?

.netdatetimeserializationjson.net

提问by LozzaDude

I've been using an old version of JSON.Net (4.0r4) for a while & have just updated to the latest one (4.5r11). I've noticed that dates used to be formatted like:

我一直在使用旧版本的 JSON.Net (4.0r4) 并刚刚更新到最新版本 (4.5r11)。我注意到以前的日期格式如下:

2013-03-20T09:00:00.119Z

2013-03-20T09:00:00.119Z

but are now:

但现在:

2013-03-20T09:00:00.119

2013-03-20T09:00:00.119

The Z is missing at the end. According to Wikipedia:

最后缺少 Z。根据维基百科:

If the time is in UTC, add a Z directly after the time without a space

如果时间是UTC,直接在时间后面加一个Z,不带空格

This has broken a lot of my JavaScript code as I have a method that converts this into a DateTimeobject & it expects the Z. I can fix it by altering this function I use to do this & I've found out that I can set the DateTimeZoneHandlingto DateTimeZoneHandling.Utcbut this means I would have to change a lot of C# code in multiple projects.

这破坏了我的很多 JavaScript 代码,因为我有一个方法可以将它转换为一个DateTime对象,并且它需要Z. 我可以通过更改我用来执行此操作的此函数来修复它,并且我发现我可以将 设置DateTimeZoneHandlingDateTimeZoneHandling.Utc但这意味着我必须在多个项目中更改大量 C# 代码。

I'm just wondering why this has changed.

我只是想知道为什么这会改变。

Thanks...

谢谢...

回答by Chris Moschini

What browser(s) are you seeing this occur in? Since the issue you're actually coping with is Javascript parsing, in my experience that problem is actually the millisecond rounding, not the presence of a Z or not.

您在什么浏览器中看到了这种情况?由于您实际处理的问题是 Javascript 解析,根据我的经验,该问题实际上是毫秒舍入,而不是是否存在 Z。

Try this in IE9: http://jsfiddle.net/b9chris/HaBP8/

在 IE9 中试试这个:http: //jsfiddle.net/b9chris/HaBP8/

'2013-06-13T20:43:55.6',
'2013-06-13T20:43:55.61',
'2013-06-13T20:43:55.61Z',
'2013-06-13T20:43:55.611',
'2013-06-13T20:43:55.611Z'

In most browsers all dates parse fine; in IE9 the first 3 fail, regardless of a Z or no, because IE9 requires 3 places for the milliseconds number. The second 2 succeed, with and without the Z. What matters is 3 millisecond digits - the Z is irrelevant, including because Javascript does not contain a DateTimeKind like .Net does, so Z or no is irrelevant to how Javascript internalizes the date. Because the number of millisecond digits will sometimes be one or 2 depending on the time, if you're passing timestamps you'll get random-seeming failures.

在大多数浏览器中,所有日期都可以很好地解析;在 IE9 中,前 3 个失败,无论 Z 与否,因为 IE9 需要 3 个位置作为毫秒数。第二个 2 成功,有和没有 Z。重要的是 3 毫秒数字 - Z 无关紧要,包括因为 Javascript 不包含像 .Net 那样的 DateTimeKind,所以 Z 与否与 Javascript 如何内部化日期无关。因为毫秒数有时会根据时间为 1 或 2,所以如果您传递时间戳,您将获得看似随机的失败。

I've reported this as a bug on the Json.Net Codeplex page; it was dismissed by the maintainer in the comments of the bug and closed. Go open source.

我已将此报告为 Json.Net Codeplex 页面上的错误;它在错误的评论中被维护者驳回并关闭。去开源。

You can work around this bug using the code in this answer:

您可以使用此答案中的代码解决此错误:

https://stackoverflow.com/a/15939945/176877

https://stackoverflow.com/a/15939945/176877

To be clear, the lack of a Z is incorrect on JSON.Net's part if it emits without it for DateTimeKind.UTC, but it is not an invalid ISO-8601 date more generally - no Z implicitly means Local Time:

需要明确的是,如果 JSON.Net 为 DateTimeKind.UTC 发出没有 Z 的部分,则缺少 Z 是不正确的,但更一般地说,它不是无效的 ISO-8601 日期 - 没有 Z 隐式表示本地时间:

http://en.wikipedia.org/wiki/ISO_8601#Times

http://en.wikipedia.org/wiki/ISO_8601#Times

If no UTC relation information is given with a time representation, the time is assumed to be in local time.

如果没有给出带有时间表示的 UTC 关系信息,则假定时间为本地时间。

And as mentioned above Javascript's parsing doesn't care about the Z, so for your purposes, it doesn't matter.

并且如上所述,Javascript 的解析不关心 Z,因此就您的目的而言,这无关紧要。

Note also you might not actually be passing UTC to JSON.Net and triggering this issue. DateTime objects in C# can be of kind Local, Unspecified, or UTC. It's not fair to assume that DateTimes that aren't UTC are in fact UTC; passing it without timezone information is the safest bet. The .Net DateTime structure punts on timezones, so JSON.Net is left with no choice but to emit default DateTimes (DateTimeKind.Unspecified) as Local, barring integration with a .Net TimeZone library.

另请注意,您实际上可能不会将 UTC 传递给 JSON.Net 并触发此问题。C# 中的 DateTime 对象可以是Local、Unspecified 或 UTC 类型。假设不是 UTC 的 DateTimes 实际上是 UTC 是不公平的;在没有时区信息的情况下传递它是最安全的选择。.Net DateTime 结构针对时区,因此 JSON.Net 别无选择,只能将默认日期时间 (DateTimeKind.Unspecified) 作为本地发出,除非与.Net TimeZone 库集成。

回答by outcoldman

You can change how DateTime will be serialized, check this from JSON.NET author: Good (Date)Times with Json.NET

您可以更改 DateTime 的序列化方式,请查看 JSON.NET 作者:Good (Date)Times with Json.NET

回答by Vitaliy Markitanov

If you have UTC data on server you should explicitly set DateTimeZoneHandling property

如果服务器上有 UTC 数据,则应明确设置 DateTimeZoneHandling 属性

 //serializer fix
        config.Formatters.Clear();
        config.Formatters.Add(new JsonMediaTypeFormatter()
        {
            SerializerSettings = new JsonSerializerSettings() {
                ContractResolver=new CamelCasePropertyNamesContractResolver(),
                DateTimeZoneHandling = DateTimeZoneHandling.Utc},

        });

After this DateTime has "Z" at the end: 2017-05-11T00:35:20.8242381Z

在此日期时间结束后有“Z”:2017-05-11T00:35:20.8242381 Z