自定义多态Newtonsoft JSON解串器

时间:2012-10-22 13:56:37

标签: .net json.net

我有一个递归数据结构。有点像...

Public Class Comparison
    Property Id As Integer
End Class

Public Class SimpleComparison
    Inherits Comparison
    Property Left As String
    Property Right As String
End Class

Public Class ComplexComparison
    Inherits Comparison
    Property Left As Comparison
    Property Right As Comparison
End Class

我需要从JSON反序列化。

如您所见,确定是使用ComplexComparison还是SimpleComparison的唯一方法是确定.Left值是字符串还是对象。 (注意他们要么都是字符串,要么都是对象)

所以,我正在编写自定义转换器并且已经做到了这一点......

Public Class ComparisonConverter
    Inherits Newtonsoft.Json.JsonConverter
    ''<Snip>
Public Overrides Function ReadJson(reader As Newtonsoft.Json.JsonReader, objectType As Type, existingValue As Object, serializer As Newtonsoft.Json.JsonSerializer) As Object
    Dim obj As JObject = TryCast(serializer.Deserialize(Of JToken)(reader), JObject)
    If obj IsNot Nothing Then
            ''We''ve got something to work with
        Dim Id As Integer = obj("Id").ToObject(Of Integer)()

            ''Check if we''re instantiating a simple or a complex comparison
        If obj("Left").GetType.IsAssignableFrom(GetType(JValue)) Then
            ''LHS is a string - Simple...
            Return New SimpleComparison With {
                .Id = Id,
                .Left = obj("Left").ToObject(Of String)(),
                .Right = obj("Right").ToObject(Of String)()}
        Else
            Return New ComplexComparison With {
            .Id = Id,
            .Left = ???, '' <<Problem
            .Right = ???}'' <<Problem
        End If
    Else
        Return Nothing
    End If
End Function
End Class

由于对象复杂而导致If的分支是我被卡住的地方。如何在obj("Left")obj("Right")(类型为JToken)上重新调用反序列化器?或者我应该将它们转换为JObject然后将此代码分解为单独的函数并递归调用它?

1 个答案:

答案 0 :(得分:2)

事实证明这比我想象的要简单,JSON.Net为我做了所有繁重的工作......

Public Overrides Function ReadJson(reader As Newtonsoft.Json.JsonReader, objectType As Type, existingValue As Object, serializer As Newtonsoft.Json.JsonSerializer) As Object
    Dim Ret As Comparison
    Dim JComparison As JObject = JObject.Load(reader)
    If JComparison("Left").GetType.IsAssignableFrom(GetType(JValue)) Then
        Ret = New SimpleComparison
    Else
        Ret = New ComplexComparison
    End If
    serializer.Populate(JComparison.CreateReader(), Ret)
    Return Ret
End Function