9

次のクラスを定義しています。

<TypeConverter(GetType(ExpandableObjectConverter))>
<DataContract()>
Public Class Vector3

   <DataMember()> Public Property X As Double
   <DataMember()> Public Property Y As Double
   <DataMember()> Public Property Z As Double

   Public Overrides Function ToString() As String

      Return String.Format("({0}, {1}, {2})",
                           Format(X, "0.00"),
                           Format(Y, "0.00"),
                           Format(Z, "0.00"))

   End Function

End Class

を使用して、DataContractJsonSerializer期待どおりに次の JSON を受け取ります。

{
  "Vector": {
    "X": 1.23,
    "Y": 4.56,
    "Z": 7.89
  }
}

ただし、JSON.NET は以下を生成します。

{
  "Vector": "(1.23, 4.56, 7.89)"
}

クラスから属性を削除するとExpandableObjectConverter、JSON.NET は期待どおりの結果を生成します (DataContractJsonSerializer と同じ)。

残念ながらExpandableObjectConverter、クラスがプロパティ グリッドで動作するようにする必要があります。

JSON.NET に無視するように指示する方法はありますExpandableObjectConvertersか?

DataContractJsonSerializer列挙型を文字列表現にシリアル化する方がはるかに簡単なので、代わりに JSON.NET を使用することを好みます。

4

3 に答える 3

13

Rivers の回答には感謝していますが、問題のあるクラスごとにカスタム JsonConverter を構築するのではなく、(DataContractJsonSerializer のように) すべての展開可能なオブジェクト コンバーターを自動的に無視するソリューションを本当に探しています。

次の2つの解決策を見つけました。

  1. 代わりに組み込みの DataContractJsonSerializer を使用してください (JSON.NET のその他の便利さを犠牲にして)。
  2. カスタム ExpandableObjectConverter を使用します (以下を参照)。

デフォルトの ExpandableObjectConverter は文字列との変換をサポートしているため、JSON.NET は文字列を使用してクラスをシリアル化しています。これに対抗するために、文字列との間の変換を許可しない独自の展開可能なオブジェクト コンバーターを作成しました。

Imports System.ComponentModel

Public Class SerializableExpandableObjectConverter
   Inherits ExpandableObjectConverter

   Public Overrides Function CanConvertTo(context As System.ComponentModel.ITypeDescriptorContext, destinationType As System.Type) As Boolean

      If destinationType Is GetType(String) Then
         Return False
      Else
         Return MyBase.CanConvertTo(context, destinationType)
      End If

   End Function

   Public Overrides Function CanConvertFrom(context As System.ComponentModel.ITypeDescriptorContext, sourceType As System.Type) As Boolean

      If sourceType Is GetType(String) Then
         Return False
      Else
         Return MyBase.CanConvertFrom(context, sourceType)
      End If

   End Function

End Class

上記のコンバーターを適用すると、JSON.NET およびプロパティ グリッド コントロールで問題なく動作します。

于 2013-07-15T21:06:12.217 に答える
1

TypeConverter を指定しているため、Json.net はそれを使用します。これを回避するには、LINQ to Json を使用して JsonConverter を作成し、必要な形式を使用します。

Public Class Vector3Converter
    Inherits JsonConverter

Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
    Dim vector = DirectCast(value, Vector3)

    serializer.Serialize(writer, New JObject() From { _
        {"X", vector.X}, _
        {"Y", vector.Y}, _
        {"Z", vector.Z} _
    })
End Sub

Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
    Dim jObject = serializer.Deserialize(Of JObject)(reader)

    Return New Vector3() With { _
        Key .X = CDbl(jObject("X")), _
        Key .Y = CDbl(jObject("Y")), _
        Key .Z = CDbl(jObject("Z")) _
    }
End Function

Public Overrides Function CanConvert(objectType As Type) As Boolean
    Return objectType = GetType(Vector3)
End Function
End Class

次に、それをタイプに割り当てます。

<TypeConverter(GetType(System.ComponentModel.ExpandableObjectConverter))> _
<DataContract> _
<JsonConverter(GetType(Vector3Converter))> _
Public Class Vector3
End Class

私はもともとこれにC#を使用し、VBへのオンラインコンバーターを使用したため、少しずれている可能性があります。

于 2013-07-11T04:54:24.123 に答える