我是 JSON.NET 新手,我正在尝试将 JSON 字符串反序列化为包含只读属性的简单 .NET 对象。
我尝试反序列化的 JSON 包含此只读属性(当然是"错误"的)。问题是,另一个属性现在不会获得 JSON 字符串中给出的值,而是获取只读属性的值。我本来希望 JSON.NET 抛出错误或只是忽略只读属性,但永远不会让另一个属性获得只读属性的值。我错过了什么吗?
或者换句话说:为什么DeSerPerson.Communications.Items(1)的值。ComValue 更改,当 getEMail 的返回语句更改时?
解决方法:如何告诉序列化程序序列化 getEmail,但反序列化程序忽略它,以防它存在?
我在这里创建了一个小提琴: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
属性返回对Items(1)
的引用,因为这是带有 ComType = 2
的项。
至于在反序列化时"忽略"对象,您可以轻松使用 clone 方法。这样,您可以从 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
读取属性时返回克隆的对象:
Public ReadOnly Property getEMail As Communication
Get
Return Items.Find(Function(x) x.ComType = 2).Clone()
End Get
End Property
当然,这不是一个最佳的代码。这只是为了向您展示事情是如何工作的:)