JSON.NET: 反序列化为具有只读属性的对象会产生意外结果
JSON.NET: Deserialization into an object with read-only properties yields unexpected results
我是 JSON.NET 的新手,我正在尝试将 JSON 字符串反序列化为包含只读 属性.[=13= 的简单 .NET 对象]
我正在尝试反序列化的 JSON 包含此只读 属性(当然 "wrong" 是什么)。问题是,另一个 属性 现在没有获得 JSON 字符串中给定的值,而是只读 属性 的值。我本以为 JSON.NET 会抛出一个错误或简单地忽略只读 属性,但永远不会得到另一个 属性 只读 属性 的值。
我错过了什么吗?
或者换句话说:
为什么DeSerPerson.Communications.Items(1).ComValue 的值在getEMail 的return 语句发生变化时发生变化?
解决方法:如果它存在,我如何告诉序列化器序列化 getEmail 但反序列化器忽略它?
我在这里创建了一个fiddle:https://dotnetfiddle.net/tUMQxF
第一个答案后略作修改。
Imports System
Imports System.Collections.Generic
Imports Newtonsoft.Json
Public Class Communication
Property ComType As Integer
Property ComValue As String
End Class
Public Class Communications
Private Property _fixedCommunication As New Communication With {.ComType = 2, .ComValue = "FixedEmail@web.de"}
Public Property Items As New List(Of Communication)
Public ReadOnly Property getEMail As Communication
Get
Return Items.Find(Function(x) x.ComType = 2) ' Yields unexpected result: DeSerPerson.Communications.Items(1).ComValue = Fred.Flintstone@web.de
'Return _fixedCommunication ' Yields expected result: DeSerPerson.Communications.Items(1).ComValue = NewEmailAddress@web.de, though "error" would be a more intuitive result to me
End Get
End Property
End Class
Public Class Person
Property Name As String
Property Communications As New Communications
End Class
Public Module Deserialization
Public Sub Main()
'The following Json-String was the result of the following process:
' 1. Deserialization of Person with Email-Address Fred.Flintstone@web.de
' 2. Sent to javascript via WebMethod
' 3. In javascript the Email-Address was changed to NewEmailAddress@web.de
' 4. The whole object (including the read-only property) was sent back resulting in the following JSON:
'Dim PersonJson = "
'{
' 'Name': 'Fred Flintstone'
' ,'Communications': {
' 'Items':[
' {'ComType':1,'ComValue':'0711-4665'}
' ,{'ComType':2,'ComValue':'NewEmailAddress@web.de'}
' ]
' ,'getEMail':
' {'ComType':2,'ComValue':'Fred.Flintstone@web.de'}
' }
'}".Replace("'", """")
Dim PersonJson = "{'Name': 'Fred Flintstone','Communications':{'Items':[{'ComType':1,'ComValue':'0711-4665'},{'ComType':2,'ComValue':'NewEmailAddress@web.de'}],'getEMail':{'ComType':2,'ComValue':'Fred.Flintstone@web.de'}}}".Replace("'", """")
Dim DeSerPerson = JsonConvert.DeserializeObject(Of Person)(PersonJson)
Console.WriteLine("Result for DeSerPerson.Communications.Items(1).ComValue:")
Console.WriteLine("--------------------------------------------------------")
Console.WriteLine("Expected : NewEmailAddress@web.de (or Error)")
Console.WriteLine("but result is: " & DeSerPerson.Communications.Items(1).ComValue) ' Fred.Flintstone@web.de
'Console.ReadLine()
End Sub
End Module
解释很简单。反序列化器只是填充现有对象中的值,而不是创建一个新对象并将其分配给您的 属性。
请注意,Readonly
修饰符声明 属性 的值(即对对象的引用)不能更改,但 Communication
的属性不能更改对象本身。
在这种情况下,您的 getEmail
属性 return 是对 Items(1)
的引用,因为那是带有 ComType = 2
的项目。
至于"ignore"反序列化时的对象,可以很方便的使用clone方法。这样,您 return 来自 getEmail
的相同值,但不是同一个对象:
将克隆方法添加到Communication
:
Public Class Communication
Property ComType As Integer
Property ComValue As String
Public Function Clone() As Communication
Return New Communication() With {.ComType = Me.ComType, .ComValue = Me.ComValue}
End Function
End Class
Return读取属性时的克隆对象:
Public ReadOnly Property getEMail As Communication
Get
Return Items.Find(Function(x) x.ComType = 2).Clone()
End Get
End Property
当然这不是最佳代码。这只是为了向您展示它是如何工作的:)
我是 JSON.NET 的新手,我正在尝试将 JSON 字符串反序列化为包含只读 属性.[=13= 的简单 .NET 对象]
我正在尝试反序列化的 JSON 包含此只读 属性(当然 "wrong" 是什么)。问题是,另一个 属性 现在没有获得 JSON 字符串中给定的值,而是只读 属性 的值。我本以为 JSON.NET 会抛出一个错误或简单地忽略只读 属性,但永远不会得到另一个 属性 只读 属性 的值。 我错过了什么吗?
或者换句话说: 为什么DeSerPerson.Communications.Items(1).ComValue 的值在getEMail 的return 语句发生变化时发生变化?
解决方法:如果它存在,我如何告诉序列化器序列化 getEmail 但反序列化器忽略它?
我在这里创建了一个fiddle:https://dotnetfiddle.net/tUMQxF 第一个答案后略作修改。
Imports System
Imports System.Collections.Generic
Imports Newtonsoft.Json
Public Class Communication
Property ComType As Integer
Property ComValue As String
End Class
Public Class Communications
Private Property _fixedCommunication As New Communication With {.ComType = 2, .ComValue = "FixedEmail@web.de"}
Public Property Items As New List(Of Communication)
Public ReadOnly Property getEMail As Communication
Get
Return Items.Find(Function(x) x.ComType = 2) ' Yields unexpected result: DeSerPerson.Communications.Items(1).ComValue = Fred.Flintstone@web.de
'Return _fixedCommunication ' Yields expected result: DeSerPerson.Communications.Items(1).ComValue = NewEmailAddress@web.de, though "error" would be a more intuitive result to me
End Get
End Property
End Class
Public Class Person
Property Name As String
Property Communications As New Communications
End Class
Public Module Deserialization
Public Sub Main()
'The following Json-String was the result of the following process:
' 1. Deserialization of Person with Email-Address Fred.Flintstone@web.de
' 2. Sent to javascript via WebMethod
' 3. In javascript the Email-Address was changed to NewEmailAddress@web.de
' 4. The whole object (including the read-only property) was sent back resulting in the following JSON:
'Dim PersonJson = "
'{
' 'Name': 'Fred Flintstone'
' ,'Communications': {
' 'Items':[
' {'ComType':1,'ComValue':'0711-4665'}
' ,{'ComType':2,'ComValue':'NewEmailAddress@web.de'}
' ]
' ,'getEMail':
' {'ComType':2,'ComValue':'Fred.Flintstone@web.de'}
' }
'}".Replace("'", """")
Dim PersonJson = "{'Name': 'Fred Flintstone','Communications':{'Items':[{'ComType':1,'ComValue':'0711-4665'},{'ComType':2,'ComValue':'NewEmailAddress@web.de'}],'getEMail':{'ComType':2,'ComValue':'Fred.Flintstone@web.de'}}}".Replace("'", """")
Dim DeSerPerson = JsonConvert.DeserializeObject(Of Person)(PersonJson)
Console.WriteLine("Result for DeSerPerson.Communications.Items(1).ComValue:")
Console.WriteLine("--------------------------------------------------------")
Console.WriteLine("Expected : NewEmailAddress@web.de (or Error)")
Console.WriteLine("but result is: " & DeSerPerson.Communications.Items(1).ComValue) ' Fred.Flintstone@web.de
'Console.ReadLine()
End Sub
End Module
解释很简单。反序列化器只是填充现有对象中的值,而不是创建一个新对象并将其分配给您的 属性。
请注意,Readonly
修饰符声明 属性 的值(即对对象的引用)不能更改,但 Communication
的属性不能更改对象本身。
在这种情况下,您的 getEmail
属性 return 是对 Items(1)
的引用,因为那是带有 ComType = 2
的项目。
至于"ignore"反序列化时的对象,可以很方便的使用clone方法。这样,您 return 来自 getEmail
的相同值,但不是同一个对象:
将克隆方法添加到Communication
:
Public Class Communication
Property ComType As Integer
Property ComValue As String
Public Function Clone() As Communication
Return New Communication() With {.ComType = Me.ComType, .ComValue = Me.ComValue}
End Function
End Class
Return读取属性时的克隆对象:
Public ReadOnly Property getEMail As Communication
Get
Return Items.Find(Function(x) x.ComType = 2).Clone()
End Get
End Property
当然这不是最佳代码。这只是为了向您展示它是如何工作的:)