【问题标题】:Deserialize JSON which can have different objects under same property name反序列化可以在相同属性名称下具有不同对象的 JSON
【发布时间】:2016-08-31 10:37:03
【问题描述】:

我正在使用 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 类型的对象,并在其属性 result 中存储一个 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
    Public Property result As Result
    Public Property resultRecords As Record()
End Class

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

谢谢!

【问题讨论】:

  • tid 是否表示类型?意思是,所有第一个都是4,所有第二个都是3?
  • 不幸的是,@Plutonix,tid 是一个“事务 id”,它将响应与它们的原始请求建立索引并将其配对,其中 postdata 也是 JSON 并且必须发送一个增量 tid 值。但是感谢您的帮助!

标签: json vb.net json.net deserialization


【解决方案1】:

由于同一属性的 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> 属性添加到Response 类中的result 属性:

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

【讨论】:

  • 你就是男人!它就像一个魅力。另外,它还让我免去了让班级结构复杂化的麻烦。它可能看起来很少,但为了读者,我对我发布的样本进行了深度修剪。我的第一个想法是要求程序的其他部分在两个不同的地方查找记录。您的解决方案使不常见的方案非常适合。非常感谢!
  • 没问题;很高兴我能提供帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多