Megrez7 Megrez7 - 1 month ago 4x Question

Deserialise JSON message of two types

I try to consume web service returning JSON messages. Each method returns relevant JSON message (typically an array) or JSON error message (not an array).

Examples of UserList and Error messages:

"full_name":"John Smith"
"full_name":"Anne Steward"

" message":"Unknown login"

Because code does not know which message to expect, I have created two classes where UserList inherits from BaseResponse (an error message class). I have used inheritance, as all other methods like GetCarList, etc. are suitable of returning an error message as well. So no need to declare error fields multiple times. That had to be smart - I will always get or UserList fields or error message fields in the same object.

Public Class BaseResponse

Public success As Boolean
Public message As String

End Class

Public Class UserListResponse
Inherits BaseResponse

Public id As Integer
Public login As String
Public full_name As String

End Class

The problem is, that UserListResponse JSON message is an array, while ErrorMessage JSON is not an array. So deserialising will work when JSON will be UserList but will not work when JSON will be an error message:

JsonConvert.DeserializeObject(Of List(Of UserListResponse))(ReceivedJSONMessage)

Any ideas how to tackle this in smart way?


If you are certain that both of your return classes are working for deserializing the json correctly you just need in essence: "Am I a list or a string?" to ask for one path or the other. In that case I would implement a generic checker that exists one level over both of your returns as such:

Private Function ReturnString() As String
  Return "I am a string"
End Function

Private Function ReturnList() As List(Of String)
  Return New List(Of String)({"A", "B", "C"})
End Function

Private Function DetermineReturn(Of T)() As Object
  If GetType(T) = GetType(String) Then
    Return ReturnString()
  ElseIf GetType(T) = GetType(List(Of String)) Then
    Return ReturnList()
    Return "Not sure of Type"
  End If
End Function

Sub Main()
  Dim testString = "Hello"

  Dim s = DetermineReturn(Of String)()
  Dim list = DetermineReturn(Of List(Of String))()
  Dim unknown = DetermineReturn(Of Integer)()

  Console.WriteLine("First Set")
  Console.WriteLine("Second Set")
  CType(list, List(Of String)).ForEach(Sub(x) Console.WriteLine(x))
  Console.WriteLine("Third Set")

End Sub

Essentially I mocked up two functions: 'ReturnString' and 'ReturnList' which return two distinctly different types. I then make up another method called 'DetermineReturn' that uses a generic (Of T), to then interrogate what the incoming call is. It then simply wraps the two methods based on call for ease of reuse. Example works in Main.