JSON.Net反序列化MailAddress

时间:2013-09-02 05:54:28

标签: vb.net serialization 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属性,它就会正确创建一个邮件对象,但之后的任何属性都不能正确反序列化。

1 个答案:

答案 0 :(得分:0)

我认为问题是你的ReadJson方法在读者完成时会使读者错误定位,从而弄乱了反序列化过程的其余部分。

将读者视为JSON数据的仅向前游标。调用ReadJson时,它的位置使得它即将读取转换器说它可以处理的下一个项目。对于EmailConverter,它的位置即将阅读JSON的这一部分:

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

由于转换器应该处理整个Email对象,因此需要使用 all 该对象的JSON。我认为正在发生的事情是读者没有进入最后阶段。您可以通过在提取Address值之后继续阅读更多来修复它,注意不要超出Email对象的末尾,但这种方法容易出错。更好的想法是使用JSON.Net的内置LINQ-to-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