JSON.Net反序列化邮件地址



我有一个对象,它包含一个名为Email的属性,类型为System.Net.Mail.MailAddress。我能够用JSON.Net序列化我的对象并将其存储在数据库中。但是,我无法成功地反序列化我的对象。我得到的错误信息是:

找不到用于类型System.Net.Mail.MailAddress的构造函数。类应该有一个默认构造函数、一个带参数的构造函数或一个用JsonConstructor属性标记的构造函数。路径"Item1.Email.DisplayName".

我知道MailAddress没有默认的构造函数,这就是我收到这个错误的原因。我的问题是,有没有办法在不转换属性类型的情况下解决这个问题?我看到有自定义转换器,但我没有任何运气让JSON.Net成功地反序列化这一属性。

更新

让我详细说明一下这个物体是什么样子的,以及我尝试过什么。对象看起来像这样:

{
  "Item1": {
    "ReceiveNewsletter": false,
    "HomePhone": "074567 8901",
    "SpouseTitle": null,
    "SpouseFirstName": null,
    "SpouseLastName": null,
    "Address": {
      "StreetAddress1": "123 Fake Street",
      "StreetAddress2": null,
      "City": null,
      "State": "QLD",
      "PostalCode": "4627",
      "Suburb": "Abercorn",
      "AustralianAddress": true
    },
    "CustomerAddresses": [],
    "ID": -1,
    "Title": "",
    "FirstName": "James",
    "LastName": "Dean",
    "DisplayName": "James Dean",
    "Email": {
      "DisplayName": "",
      "User": "jamesdean890",
      "Host": "fake.com.au",
      "Address": "jamesdean890@fake.com.au"
    },
    "WorkPhone": null,
    "OtherPhone": "",
    "CellPhone": "0423 456 789",
    "Notes": null
  },
  "Item2": {
    "ID": -1,
    "CustomerID": -1,
    "Pet": {
      "ID": -1,
      "Name": "Fae",
      "Breed": "Puppy Dog",
      "DateOfDeath": "2013-08-28T00:00:00-05:00",
      "ServiceDate": "2013-08-28T00:00:00-05:00",
      "ContactDate": "0001-01-01T00:00:00-06:00",
      "PetGender": 1,
      "ReferralClinicID": 462,
      "ReferralPaidDate": null,
      "Row": "u0000",
      "Plot": -1,
      "CollectedBy": null,
      "DeliverDate": "0001-01-01T00:00:00-06:00",
      "DeliveredBy": null,
      "Customer": null,
      "RenewDate": null
    },
    "Service": {
      "ID": -1,
      "Quantity": 1,
      "Price": 285.0,
      "ProductName": "Cremation",
      "ProductID": 1,
      "LineItemState": 0,
      "Plaque": null,
      "IsPlaque": false,
      "Void": false
    },
    "LineItems": [],
    "Notes": "",
    "EnteredBy": null,
    "IsRenewal": false,
    "IsLocked": false,
    "CreateDate": "0001-01-01T00:00:00-06:00",
    "OrderTotal": 285.0
  }
}

在我的联系人课程中,我有这样的东西:

<JsonConverter(GetType(EmailConverter))>
Public Property Email() As Net.Mail.MailAddress
    Get
        Return _Email
    End Get
    Set(ByVal value As Net.Mail.MailAddress)
        _Email = value
    End Set
End Property

然后,我发现了一个类似这样的转换器:

Public Class EmailConverter
    Inherits JsonConverter
    Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
        Dim mailAddress As System.Net.Mail.MailAddress = Nothing
        If objectType = GetType(System.Net.Mail.MailAddress) Then
            While reader.Path <> "Item1.Email.Address"
                reader.Read()
            End While
            reader.Read()
            mailAddress = New Net.Mail.MailAddress(reader.Value.ToString)
        End If
        Return mailAddress
    End Function
    Public Overrides Function CanConvert(objectType As Type) As Boolean
         Return objectType = GetType(System.Net.Mail.MailAddress)
    End Function
    Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
    End Sub
End Class

通过使用该属性并将转换器添加到序列化程序,只要序列化程序达到Email属性,它就会正确创建邮件对象,但之后的任何属性都不会正确反序列化。

我认为问题在于ReadJson方法在完成时使读取器的位置不正确,从而打乱了反序列化过程的其余部分。

将读取器视为JSON数据的仅向前的游标。当ReadJson被调用时,它的位置使得它即将读取转换器所说的它可以处理的下一个项目。在您的EmailConverter的情况下,它的位置将刚好读取JSON:的这一部分

{
  "DisplayName": "",
  "User": "jamesdean890",
  "Host": "fake.com.au",
  "Address": "jamesdean890@fake.com.au"
}

由于转换器应该处理整个Email对象,因此它需要消耗该对象的所有JSON。我认为现在的情况是读者没有进入最后阶段。您可能可以通过在提取Address值后继续进一步读取来修复它,注意不要超出Email对象的末尾,但这种方法很容易出错。一个更好的想法是使用JSON.Net内置的LINQ到JSON功能,使您可以轻松地将整个Email对象作为一个块读取,然后从中只挑选出您需要的部分。这将使读取器在反序列化的其余部分处于正确的位置,然后您就不必担心了。它还大大简化了代码。

以下是我如何编写EmailConverter:

Imports System.Net.Mail
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class EmailConverter
    Inherits JsonConverter
    Public Overrides Function CanConvert(objectType As Type) As Boolean
        Return objectType = GetType(MailAddress)
    End Function
    Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
        Dim jsonObject As JObject = JObject.Load(reader)
        Dim address As String = jsonObject("Address").Value(Of String)()
        Dim mailAddress As MailAddress = New MailAddress(address)
        Return mailAddress
    End Function
    Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
        serializer.Serialize(writer, value)
    End Sub
End Class

相关内容

  • 没有找到相关文章

最新更新