JSON.NET:反序列化为具有只读属性的对象会产生意外的结果



我是 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

当然,这不是一个最佳的代码。这只是为了向您展示事情是如何工作的:)

相关内容

  • 没有找到相关文章

最新更新