1

我有一个对象,其中包含一个名为 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 属性,它将正确创建一个邮件对象,但它之后的任何属性都不会正确反序列化。

4

1 回答 1

0

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

将阅读器想象成 JSON 数据的只进游标。当 ReadJson 被调用时,它被定位为即将读取转换器说它可以处理的下一个项目。在你的情况下EmailConverter,它将被定位为即将读取 JSON 的这一部分:

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

由于转换器应该处理整个Email对象,因此它需要使用该对象的所有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
于 2013-09-02T08:45:14.533 回答