我有一个对象,它包含一个名为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