1

というタイプの Email というプロパティを含むオブジェクトがありますSystem.Net.Mail.MailAddress。オブジェクトをシリアライズJSON.Netしてデータベースに保存できます。ただし、オブジェクトを正常に逆シリアル化できません。私が得るエラーメッセージは次のとおりです。

タイプ に使用するコンストラクタが見つかりませんSystem.Net.Mail.MailAddress。クラスには、デフォルトのコンストラクター、引数を持つ 1 つのコンストラクター、または JsonConstructor 属性でマークされたコンストラクターのいずれかが必要です。パス「Item1.Email.DisplayName」。

MailAddress にはデフォルトのコンストラクターがないことを理解しています。そのため、このエラーが発生しています。私の質問は、プロパティの型を変換せずにこれを回避する方法はありますか? カスタム コンバーターがあるようですが、JSON.Net でこの 1 つのプロパティを正常に逆シリアル化することができませんでした。

アップデート

オブジェクトがどのように見えるか、および私が試したことについて、もう少し詳しく説明します。オブジェクトは次のようになります。

{
  "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"
}

コンバーターはオブジェクト全体を処理することになっているため、そのオブジェクトのすべての JSON を使用Emailする必要があります。何が起こっているかというと、読者が閉じ括弧に進んでいないということだと思います。値を抽出した後、オブジェクトの末尾を超えないように注意しながら、もう少し読み続けることでおそらく修正できますが、この方法ではエラーが発生しやすくなります。より良いアイデアは、JSON.Net の組み込みの LINQ-to-JSON 機能を使用して、オブジェクト全体をチャンクとして簡単に読み取り、そこから必要な部分だけを選択できるようにすることです。これにより、残りの逆シリアル化のためにリーダーが正しく配置されたままになり、それについて心配する必要はありません。また、コードが大幅に簡素化されます。AddressEmailEmail

これが私が書く方法です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 に答える