如何解析 Newtonsoft JSON 中的 TimeSpan 值

s d*_*s d 4 .net c# json timespan json.net

我想解析 JSON 字符串并使用该token.Type属性来检测 type 的值JTokenType.TimeSpan

我不知道如何在我的输入字符串中表达 TimeSpan,一切似乎都被解释为 JTokenType.String。

var timeSpanString = TimeSpan.FromHours(1).ToString();
testString = string.Format(@"{{""Value"": ""{0}"" }}", timeSpanString);
var statObject = JObject.Parse(testString);
JToken token = statObject["Value"];
var tokenValue = token.ToString();
var tokenType = token.Type; // JTokenType.String
Run Code Online (Sandbox Code Playgroud)

我什至试过:

JValue jValue = new JValue("test");
jValue.Value = TimeSpan.FromHours(1);
bool isTimeSpan = jValue.Type == JTokenType.TimeSpan; // true!
testString = string.Format(@"{{""Value"": ""{0}"" }}", jValue.Value);
var statObject = JObject.Parse(testString);
JToken token = statObject["Value"];
var tokenValue = token.ToString();
var tokenType = token.Type; // JTokenType.String
Run Code Online (Sandbox Code Playgroud)

这至少会产生一个令牌类型 JTokenType.TimeSpan的JValue对象,但在我解析它时仍然显示为 JTokenType.String。

这适用于 DateTime 对象。如何表达输入字符串,使解析的值类型为JTokenType.TimeSpan

car*_*ira 6

根据我在使用 JSON.NET 一段时间后看到的情况,在默认设置下,您永远不会解析字符串并检索带有类型的令牌JTokenType.TimeSpan(对于其他一些类型也是如此,例如 Guid 或 Uri) . 我有一个很好的猜测为什么会这样(根据我几年前使用DataContractJsonSerializer.

基本上,这是解析器可以从输入中检索到多少信息的问题。JSON 是一种非常简单的语法,它只知道数字布尔值字符串(除了数组和对象)。许多 CLR 类型没有本机 JSON 类型(Uri、DateTime、DateTimeOffset、TimeSpan 等),因此当任何 JSON 解析器读取数据时,它都会尝试使用最佳匹配。

如果您将 JSON 字符串反序列化为 CLR 数据类型,那么序列化程序有一些附加信息,可用于消除 JSON 字符串映射到的内容的歧义 - 值被反序列化到的字段/属性的类型。但是,当您将 JSON 数据反序列化为JToken对象图时,没有其他信息,并且 JSON.NET 必须选择一种类型。反序列化 JSON 字符串最自然的类型是 CLR 字符串。

但是为什么日期被正确反序列化为JTokenType.Date?IIRC,JSON.NET 阅读器有一个特殊的日期代码(由DateParseHandling枚举控制),它尝试将解析的字符串与一些预定义的格式(ISO 8601 或旧的 Microsoft ASP.NET AJAX 格式)匹配,如果它找到匹配它的字符串,它会将其读取为DateTime(或DateTimeOffset)而不是字符串。我不知道是否可以将这种行为扩展到支持TimeSpan或其他类型,但我不会感到惊讶,因为 JSON.NET 中的可扩展性非常好。