Search code examples
jsonvb.netdeserializationjson-deserialization

Dynamic JSON Deserialization with VB.NET


I get an API response in JSON in following format

{
    "stuffs": {
        "prop1": "abcd",
        "prop2": "efgh",
        "prop3": [
            {
                "content": "123456",
                "name": "abc def",
                "id": "123"
            },
            {
                "content": "789012",
                "name": "def ghi",
                "id": "456"
            }
        ]
    }
}

I have created my Class to deserialize this object as below

Public Class Prop3
    Public Property content As String
    Public Property name As String
    Public Property id As String
End Class

Public Class Stuffs
    Public Property prop1 As String
    Public Property prop2 As String
    Public Property prop3 As Prop3()
End Class

Public Class Example
    Public Property stuffs As Stuffs
End Class

Now the issue is, sometime, the response is not an array for prop3 and looks like this

{
    "stuffs": {
        "prop1": "abcd",
        "prop2": "efgh",
        "prop3": {
            "content": "123456",
            "name": "abc def",
            "id": "123"
        }
    }
}

This time I get error while deserializing as the prop3 is not array anymore bu the property declared inside my class stuffs is expecting an array of property prop3.

Is there any dynamic way to resolve this? Like if the JSON response is an array it will be treated as array

Public Property prop3 As Prop3()

and in case it is not an array then it will treated as single property

Public Property prop3 As Prop3

Please suggest how to overcome this as changing the response from the API is not feasible because it is being developed by client and I need to use it my application, so I need to find some dynamic way to resolve this.

After suggestion made by Craig, I have tried in the below way, but still it is not happening, please suggest if I am making any mistake.

Public Class SingleValueArrayConverter(Of T)
    Inherits JsonConverter

    Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal value As Object, ByVal serializer As JsonSerializer)
        serializer.Serialize(writer, value)
    End Sub

    Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal objectType As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
        Dim retVal As Object = New Object()

        If reader.TokenType = JsonToken.StartObject Then
            Dim instance As T = CType(serializer.Deserialize(reader, GetType(T)), T)
            retVal = New List(Of T)() From {
                instance
            }
        ElseIf reader.TokenType = JsonToken.StartArray Then
            retVal = serializer.Deserialize(reader, objectType)
        End If

        Return retVal
    End Function

    Public Overrides Function CanConvert(ByVal objectType As Type) As Boolean
        Return True
    End Function
End Class


Public Class myClass1
    Public Class Prop3
        Public Property content As String
        Public Property name As String
        Public Property id As String
    End Class

    Public Class Stuffs
        Public Property prop1 As String
        Public Property prop2 As String
        <JsonProperty("prop3")>
        <JsonConverter(GetType(SingleValueArrayConverter(Of Prop3)))>
        Public Property prop3 As Prop3()
    End Class

    Public Class Example
        Public Property stuffs As Stuffs
    End Class
End Class

It gives error: Unable to cast object of type 'SingleValueArrayConverter`1[myClass1.myClass+Prop3]' to type 'Newtonsoft.Json.JsonConverter'.'

Any highlight on what I am missing please.


Solution

  • It worked after changing

    Public Property prop3 As Prop3()
    

    to

    Public Property prop3 As List(Of Prop3)