JsonConvert.DeserializeObject到en-US文化

3

我添加了自定义的JsonSerializerSettings以确保日期始终反序列化为en-US culture

JsonConvert.DeserializeObject<T>(responseString, new JsonSerializerSettings()
                                { Culture = new System.Globalization.CultureInfo("en-US") });

然而,这对伊斯兰教历的日期并不适用,日期仍以阿拉伯文化历法反序列化。

为什么?我错过了什么吗?

T 先生们

public partial class T
    {
    --------------------
        public Nullable<System.DateTime> EffectiveStartDate { get; set; }
        public Nullable<System.DateTime> EffectiveEndDate { get; set; }
        public Nullable<System.DateTime> SourceDate { get; set; }
    -----------------
    }

Json响应 { ..... , "effectiveStartDate":"2018-01-02T00:00:00", .... }

反序列化后

15/04/39 12:00:00

而我的期望是

02/01/2018


3
最好提供一个[mcve]。"date is still de-serialized in ar culture calendar"这句话的意思不太清楚。(我猜你是根据调试器中DateTime.ToString的输出来判断的,但也很难确定。) - Jon Skeet
3
“EffectiveStartDate” 是一个 DateTime 类型,实际上是一个数字。你所看到的是调试器将该数字转换为易于人类阅读的格式。如果你调用 EffectiveStartDate.ToString("o"),你会看到正确的 ISO8601 日期。 - ProgrammingLlama
什么?真的吗?它不是调试器转换的值,而是反序列化的值,我的朋友。你知道为什么它给出了值15/04/39 12:00:00吗?因为当前文化是ar。所以我尝试请求JsonConverter始终使用en-US。 - TheKingPinMirza
4
@immirza,请阅读文档https://msdn.microsoft.com/library/zdtaw1bw(v=vs.110).aspx#Remarks(请参见“调用者注意事项”部分)。 - Sir Rufo
2
@immirza 我认为你误解了。你的机器设置为“ar”文化吗?如果是这样,调试器将以该格式显示值。一旦它变成DateTime,它就与序列化程序无关了。 - ProgrammingLlama
显示剩余4条评论
2个回答

7
我认为你对代码的运行方式有所误解。反序列化过程将按如下方式进行:
  1. 创建一个 T 实例(我们称之为 x)。

  2. 开始从 JSON 读取属性,并在 T 中找到匹配的属性。将 JSON 属性转换为 C# 变量,并将它们添加到 x 中的正确属性中。

  3. 当我们到达 effectiveStartDate 属性时,它将把值反序列化为 DateTime 对象。为了解析 JSON 字符串,它引用了您提供的 en-US 区域设置,以防字符串以美国格式显示日期(例如 mm/dd/yyyy)。但是,日期采用 ISO 格式,这是一种无歧义且易于计算机读取的格式,因此在这种情况下区域设置根本不重要。

  4. 将解析后的日期存储在 DateTime 对象中。DateTime 不使用特定的内部格式——它只将日期存储为数字。格式仅用于将日期序列化为字符串或向人类显示日期。

反序列化现在已完成,您可以自由地在代码中使用常规的 C# 对象。

显然,您随后会尝试在代码中或通过调试器读取x.effectiveStartDate 的值(您没有向我们展示您查看日期的确切方法)。由于您想要查看它,不可避免地,C# 会将存储在 DateTime 对象中的数字输出为人类可读的日期字符串。请注意,反序列化过程已经完成,您现在回到了应用程序的上下文环境。因此,您看到的日期格式符合 ar 区域设置及其相关的日历样式,因为这是您的应用程序的区域设置。而 en-US 区域设置仅适用于反序列化过程,该过程已经完成。

如果您希望以与应用程序文化不同的格式显示日期,则需要明确告知应用程序。例如,您可以通过 DateTimetoString 方法设置格式,或通过代码暂时更改区域设置。


0
除了ADyson上面提到的之外。
取自官方source。对于每个想更多了解DateTime的开发人员来说,这是一篇必读的文章。
在内部,所有的DateTime值都表示为自0001年1月1日午夜12:00:00以来经过的滴答数(100纳秒间隔数)。实际的DateTime值与该值在用户界面元素中显示或写入文件时出现的方式无关。DateTime值的外观是格式化操作的结果。格式化是将值转换为其字符串表示形式的过程。由于日期和时间值的外观取决于文化、国际标准、应用程序要求和个人偏好等因素,所以DateTime结构通过其ToString方法的重载提供了大量格式化日期和时间值的灵活性。默认的DateTime.ToString()方法返回使用当前区域设置的短日期和长时间模式的日期和时间值的字符串表示形式。以下示例使用默认的DateTime.ToString()方法来显示日期和时间,使用en-US文化的短日期和长时间模式,这是在运行示例的计算机上的当前文化。
DateTime date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")));
// Displays 01/03/2008 07:00:00
  [1]: https://msdn.microsoft.com/en-us/library/system.datetime(v=vs.110).aspx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接