反序列化JSON,它可以在相同的属性名称

时间:2016-05-05 15:03:59

标签: json vb.net json.net deserialization

我正在使用JSON.NET从HTTP查询反序列化JSON响应,但我遇到了问题。那是因为响应可以在同一属性下发送两种类型的对象,如下所示:

第一个案例样本(最常见):

{
  "type": "myType",
  "tid": 4,
  "action": "myAction",
  "method": "myMethod",
  "result": {
    "success": true,
    "total": 4,
    "records": [
      {
        "id": 4,
        "nome": "PRIMEIRO NOME",
        "sigla": "PN"
      },
      {
        "id": 1974,
        "nome": "SEGUNDO NOME",
        "sigla": "SN"
      },
      {
        "id": 2584,
        "nome": "TERCEIRO NOME",
        "sigla": "TN"
      },
      {
        "id": 1170,
        "nome": "QUARTO NOME",
        "sigla": "QN"
      }
    ]
  }
}

第二案例样本(罕见):

{
  "type": "myType",
  "tid": 3,
  "action": "myAction",
  "method": "myMethod",
  "result": [
    {
      "id": 4,
      "nome": "PRIMEIRO NOME",
      "sigla": "PN"
    },
    {
      "id": 1974,
      "nome": "SEGUNDO NOME",
      "sigla": "SN"
    },
    {
      "id": 2584,
      "nome": "TERCEIRO NOME",
      "sigla": "TN"
    },
    {
      "id": 1170,
      "nome": "QUARTO NOME",
      "sigla": "QN"
    }
  ]
}

我一直在使用这些类来接收第一种情况的数据:

Public Class Record
    Public Property id As Integer
    Public Property nome As String
    Public Property sigla As String
End Class

Public Class Result
    Public Property success As Boolean
    Public Property total As Integer
    Public Property records As Record()
End Class

Public Class Response
    Public Property type As String
    Public Property tid As Integer
    Public Property action As String
    Public Property method As String
    Public Property result As Result
End Class

所以它在第一个案例JSON的反序列化时运行良好,声明如下:

Dim myResponse = JsonConvert.DeserializeObject(Of Response)(myJsonString)

但是,当收到第二种情况JSON时,它会创建响应类型的对象,在其属性结果中存储结果类型的对象,属性保持为空,我需要检索的数据因此而无处存储。

我认为我应该修改类Response,因此它可以用于这个不同的数据集,这样:

Public Class Response
    Public Property type As String
    Public Property tid As Integer
    Public Property action As String
    Public Property method As String
    Public Property result As Result
    Public Property resultRecords As Record()
End Class

那么问题是:如何在适合其类型(上面的第一个示例案例)或响应时告诉JsonConvert是否将数据存储在属性 Response.result 中.resultRecords 在第二种情况下?

谢谢!

1 个答案:

答案 0 :(得分:3)

由于JSON的格式可能因同一属性而异,因此您需要一个自定义JsonConverter来处理它。转换器可以读取受影响属性的JSON,确定其格式,然后适当地填充对象。以下是您需要的代码:

Public Class ResultConverter
    Inherits JsonConverter

    Public Overrides Function CanConvert(objectType As Type) As Boolean
        Return objectType = GetType(Result)
    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)
        Dim result As Result = New Result
        If token.Type = JTokenType.Array Then
            result.records = token.ToObject(Of Record())(serializer)
            result.total = result.records.Length
            result.success = True
        Else
            serializer.Populate(token.CreateReader(), result)
        End If
        Return result
    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

要使用转换器,请在<JsonConverter>类的result属性中添加Response属性:

Public Class Response
    Public Property type As String
    Public Property tid As Integer
    Public Property action As String
    Public Property method As String
    <JsonConverter(GetType(ResultConverter))>
    Public Property result As Result
End Class

这是一个工作小提琴,表明此转换器将允许将两种JSON格式反序列化为相同的类:https://dotnetfiddle.net/NFbQ2Q