newtonsoft json 如果 class 中的目标已初始化,则将有效日期时间反序列化为可为 null 的 datetimeoffset 不同行为
newtonsoft json deserialize of valid datetime into nullable datetimeoffset different behavior if target in class was initialized
Newtonsoft JSON 今天从 NuGet(我认为是 V12)、.NET 框架 V4.7.2、Web 服务的简化示例 return 中提取出来。代码和输出如下。所有 returned 日期时间形式都声称是 UTC。当反序列化为 class 的 datetimeoffset 成员时,是否有反序列化设置选项将无时区信息视为 UTC?示例 returned 值为“2015-08-04T22:04:50”
如果 datetimeoffset 成员未标记为可为 null,则没有时区的可解析 datetimeoffset returns 默认未初始化值 (1/1/0001 12:00:00 AM +00:00)。也就是说,反序列化没有成功。使用 DateTimeOffset.Parse 解析时的相同字符串将其视为本地时区,并且 returns 是本地时区中的有效日期时间。不好,但可以用其他代码处理。
如果 datetimeoffset 成员被标记为可为空,则该成员保持为空(无),这也是不正确的。
class 中 datetimeoffset 的初始化值:8/4/2015 10:04:50 PM +00:00
Newtonsoft.Json.JsonConvert.SerializeObject 序列化字符串:{"dtoReturned":"2015-08-04T22:04:50+00:00"}
来自网络服务的序列化字符串:{"dtoReturned":"2015-08-04T22:04:50"}
datetimeoffset 的反序列化值:8/4/2015 10:04:50 PM +00:00
class 中 datetimeoffset 的未初始化值:1/1/0001 12:00:00 AM +00:00
datetimeoffset 的反序列化值:1/1/0001 12:00:00 AM +00:00
class 中 datetimeoffset 的初始化值:8/4/2025 10:04:50 PM +00:00
Newtonsoft.Json.JsonConvert.SerializeObject 序列化字符串:{"dtoReturned":"2025-08-04T22:04:50+00:00"}
来自网络服务的序列化字符串:{"dtoReturned":"2025-08-04T22:04:50"}
datetimeoffset 的反序列化值:8/4/2025 10:04:50 PM +00:00
在反序列化之前 class 中的 datetimeoffset 值什么都没有
class 中 datetimeoffset 的反序列化值什么都没有
进口System.IO
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim obj1a As New TestClass1 ' transfers_v1_incoming
obj1a.dtoReturned = DateTimeOffset.Parse("2015-08-04T22:04:50Z")
Debug.Print("initialized value of datetimeoffset in class: " & obj1a.dtoReturned.ToString)
Dim strIn As String = Newtonsoft.Json.JsonConvert.SerializeObject(obj1a)
Debug.Print("Newtonsoft.Json.JsonConvert.SerializeObject serialized string: " & strIn)
strIn = Replace(strIn, "+00:00", "")
Debug.Print("serialized string from web service: " & strIn)
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj1a.GetType)
Debug.Print("deserialzied value of datetimeoffset: " & obj1a.dtoReturned.ToString)
Dim obj1b As New TestClass1 ' transfers_v1_incoming
Debug.Print("uninitialized value of datetimeoffset in class: " & obj1b.dtoReturned.ToString)
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj1b.GetType)
Debug.Print("deserialzied value of datetimeoffset: " & obj1b.dtoReturned.ToString)
Dim obj2a As New TestClass2
obj2a.dtoReturned = DateTimeOffset.Parse("2025-08-04T22:04:50Z")
Debug.Print("initialized value of datetimeoffset in class: " & obj2a.dtoReturned.ToString)
strIn = Newtonsoft.Json.JsonConvert.SerializeObject(obj2a)
Debug.Print("Newtonsoft.Json.JsonConvert.SerializeObject serialized string: " & strIn)
strIn = Replace(strIn, "+00:00", "")
Debug.Print("serialized string from web service: " & strIn)
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj2a.GetType)
Debug.Print("deserialzied value of datetimeoffset: " & obj2a.dtoReturned.ToString)
Dim obj2b As New TestClass2
If IsNothing(obj2b.dtoReturned) Then
Debug.Print("value of datetimeoffset in class before deserialize is nothing")
Else
Debug.Print("uninitialized value of datetimeoffset in class before deserialize: " & obj2b.dtoReturned.ToString)
End If
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj2b.GetType)
If IsNothing(obj2b.dtoReturned) Then
Debug.Print("deserialzied value of datetimeoffset in class is nothing")
Else
Debug.Print("deserialzied value of datetimeoffset: " & obj2b.dtoReturned.ToString)
End If
End Sub
Class TestClass1
Public Property dtoReturned As DateTimeOffset
End Class
Class TestClass2
Public Property dtoReturned As DateTimeOffset?
End Class
结束Class
您调用 Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj.GetType)
就好像它要改变 obj
变量一样。不会的。
相反,您需要使用从此方法返回的对象。您还需要将其投射到您的 class.
obj = CType(Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj.GetType), TestClass1)
或者更简单,使用采用泛型类型定义的重载:
obj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of TestClass1)(strIn)
Newtonsoft JSON 今天从 NuGet(我认为是 V12)、.NET 框架 V4.7.2、Web 服务的简化示例 return 中提取出来。代码和输出如下。所有 returned 日期时间形式都声称是 UTC。当反序列化为 class 的 datetimeoffset 成员时,是否有反序列化设置选项将无时区信息视为 UTC?示例 returned 值为“2015-08-04T22:04:50”
如果 datetimeoffset 成员未标记为可为 null,则没有时区的可解析 datetimeoffset returns 默认未初始化值 (1/1/0001 12:00:00 AM +00:00)。也就是说,反序列化没有成功。使用 DateTimeOffset.Parse 解析时的相同字符串将其视为本地时区,并且 returns 是本地时区中的有效日期时间。不好,但可以用其他代码处理。
如果 datetimeoffset 成员被标记为可为空,则该成员保持为空(无),这也是不正确的。
class 中 datetimeoffset 的初始化值:8/4/2015 10:04:50 PM +00:00
Newtonsoft.Json.JsonConvert.SerializeObject 序列化字符串:{"dtoReturned":"2015-08-04T22:04:50+00:00"}
来自网络服务的序列化字符串:{"dtoReturned":"2015-08-04T22:04:50"}
datetimeoffset 的反序列化值:8/4/2015 10:04:50 PM +00:00
class 中 datetimeoffset 的未初始化值:1/1/0001 12:00:00 AM +00:00
datetimeoffset 的反序列化值:1/1/0001 12:00:00 AM +00:00
class 中 datetimeoffset 的初始化值:8/4/2025 10:04:50 PM +00:00
Newtonsoft.Json.JsonConvert.SerializeObject 序列化字符串:{"dtoReturned":"2025-08-04T22:04:50+00:00"}
来自网络服务的序列化字符串:{"dtoReturned":"2025-08-04T22:04:50"}
datetimeoffset 的反序列化值:8/4/2025 10:04:50 PM +00:00
在反序列化之前 class 中的 datetimeoffset 值什么都没有
class 中 datetimeoffset 的反序列化值什么都没有
进口System.IO Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim obj1a As New TestClass1 ' transfers_v1_incoming
obj1a.dtoReturned = DateTimeOffset.Parse("2015-08-04T22:04:50Z")
Debug.Print("initialized value of datetimeoffset in class: " & obj1a.dtoReturned.ToString)
Dim strIn As String = Newtonsoft.Json.JsonConvert.SerializeObject(obj1a)
Debug.Print("Newtonsoft.Json.JsonConvert.SerializeObject serialized string: " & strIn)
strIn = Replace(strIn, "+00:00", "")
Debug.Print("serialized string from web service: " & strIn)
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj1a.GetType)
Debug.Print("deserialzied value of datetimeoffset: " & obj1a.dtoReturned.ToString)
Dim obj1b As New TestClass1 ' transfers_v1_incoming
Debug.Print("uninitialized value of datetimeoffset in class: " & obj1b.dtoReturned.ToString)
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj1b.GetType)
Debug.Print("deserialzied value of datetimeoffset: " & obj1b.dtoReturned.ToString)
Dim obj2a As New TestClass2
obj2a.dtoReturned = DateTimeOffset.Parse("2025-08-04T22:04:50Z")
Debug.Print("initialized value of datetimeoffset in class: " & obj2a.dtoReturned.ToString)
strIn = Newtonsoft.Json.JsonConvert.SerializeObject(obj2a)
Debug.Print("Newtonsoft.Json.JsonConvert.SerializeObject serialized string: " & strIn)
strIn = Replace(strIn, "+00:00", "")
Debug.Print("serialized string from web service: " & strIn)
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj2a.GetType)
Debug.Print("deserialzied value of datetimeoffset: " & obj2a.dtoReturned.ToString)
Dim obj2b As New TestClass2
If IsNothing(obj2b.dtoReturned) Then
Debug.Print("value of datetimeoffset in class before deserialize is nothing")
Else
Debug.Print("uninitialized value of datetimeoffset in class before deserialize: " & obj2b.dtoReturned.ToString)
End If
Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj2b.GetType)
If IsNothing(obj2b.dtoReturned) Then
Debug.Print("deserialzied value of datetimeoffset in class is nothing")
Else
Debug.Print("deserialzied value of datetimeoffset: " & obj2b.dtoReturned.ToString)
End If
End Sub
Class TestClass1
Public Property dtoReturned As DateTimeOffset
End Class
Class TestClass2
Public Property dtoReturned As DateTimeOffset?
End Class
结束Class
您调用 Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj.GetType)
就好像它要改变 obj
变量一样。不会的。
相反,您需要使用从此方法返回的对象。您还需要将其投射到您的 class.
obj = CType(Newtonsoft.Json.JsonConvert.DeserializeObject(strIn, obj.GetType), TestClass1)
或者更简单,使用采用泛型类型定义的重载:
obj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of TestClass1)(strIn)