将 JSON 对象和数组转换为 VB.net 中的相同 class

Convert JSON object and array to same class in VB.net

我正在尝试将从第三方 API 返回的 JSON 转换为 VB.NET class 对象。问题是 JSON 有时 returns 一个节点作为对象数组,有时同一节点作为单个对象。因此,在接收到对象数组时尝试转换时,代码抛出异常。

    {
  "correlation_id": "228.9219622269229",
  "Error": {
    "messages": [
      {
        "code": "401",
        "description": "Unauthorized"
      }
    ]
  },
  "transaction_status": "Not Processed"
}

可以看到,在Error->messages节点下有一个错误信息数组。但有时,返回的 JSON 很简单,错误消息的对象类似于

{
  "correlation_id": "228.9219622269229",
  "Error": {
    "messages": {
        "code": "401",
        "description": "Unauthorized"
      }
  },
  "transaction_status": "Not Processed"
}

我尝试将此 JSON 反序列化为以下 class

Public Class PayeezyRefundResponse
    Public correlation_id As String
    Public transaction_status As String
    Public validation_status As String
    Public transaction_type As String
    Public transaction_id As String
    Public transaction_tag As String
    Public bank_resp_code As String
    Public bank_message As String
    Public [Error] As PayeezyError
End Class
Public Class PayeezyError
    Public messages As PayeezyErrorMessages()
End Class
Public Class PayeezyErrorMessages
    Public code As String
    Public description As String
End Class

但是当 JSON returns 错误消息作为单个对象时,代码会在 PayeezyError class 上抛出异常。我如何将 JSON 转换为 class 以便它在两种情况下都有效(即对象数组和单个对象)?

您可以构建一个可以处理这两种情况的自定义转换器 List(Of PayeezyErrorMessage).
此转换器始终 returns 一个 List(Of PayeezyErrorMessage),即使 JSON 包含单个对象。

注意:在代码中,PayeezyErrorMessages,复数,已经重命名为PayeezyErrorMessage,单数,因为这个class生成了单数目的。

自定义转换器作为属性添加到 属性:

<JsonConverter(GetType(PayeezyErrorsConverter(Of PayeezyErrorMessage)))>
Public Messages As List(Of PayeezyErrorMessage)

重构代码:

Public Class PayeezyRefundResponse
    ' [...]
    <JsonProperty("Error")>
    Public Errors As PayeezyErrors
End Class

Public Class PayeezyErrors
    <JsonProperty("messages")>
    <JsonConverter(GetType(PayeezyErrorsConverter(Of PayeezyErrorMessage)))>
    Public Messages As List(Of PayeezyErrorMessage)
End Class

Public Class PayeezyErrorMessage
    Public code As String
    Public description As String
End Class

自定义转换器:
► 作者部分未实现,因为您可能不需要发回此 JSON

Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq

Public Class PayeezyErrorsConverter(Of T)
    Inherits JsonConverter

    Public Overrides Function CanConvert(objectType As Type) As Boolean
        Return (objectType = GetType(List(Of T)))
    End Function

    Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
        Dim token As JToken = JToken.Load(reader)
        If token.Type = JTokenType.Array Then
            Return token.ToObject(Of List(Of T))()
        End If
        Return New List(Of T)() From {
            token.ToObject(Of T)()
        }
    End Function

    Public Overrides ReadOnly Property CanWrite() As Boolean
        Get
            Return False
        End Get
    End Property

    Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
        Throw New NotImplementedException()
    End Sub
End Class