json - 如何反序列化可以是数组或单个对象的 JSON

标签 json vb.net json.net

我对使用 JSON.net 还很陌生,并且在使用一些 json 时遇到了问题,有时作为数组出现,有时作为单个对象出现。这是我在 json 中看到的示例

它进来的一种方式......

{
  "Make": "Dodge",
  "Model": "Charger",
  "Lines": [
    {
      "line": "base",
      "engine": "v6",
      "color": "red"
    },
    {
      "line": "R/T",
      "engine": "v8",
      "color": "black"
    }
  ],
  "Year": "2013"
}

它可以进入的另一种方式
{
  "Make": "Dodge",
  "Model": "Charger",
  "Lines": {
    "line": "base",
    "engine": "v6",
    "color": "red"
  },
  "Year": "2013"
}

这是我一直在使用的代码,它以第一种方式工作并在第二种情况下引发异常。一直在网上搜索实现这一点的方法,我真的被困住了。
Public Class jsonCar
    Public Property make As String
    Public Property model As String
    Public Property lines As List(Of jsonCarLines)
    Public Property year As String
End Class

Public Class jsonCarLines
    Public Property line As String
    Public Property engine As String
    Public Property color As String
End Class

Module Module1
    Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
    'Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""R/T"",""engine"":""v8"",""color"":""black""},""Year"":""2013""}"
    Sub Main()
        Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)

        Console.WriteLine("Make: " & car.make)
        Console.WriteLine("Model: " & car.model)
        Console.WriteLine("Year: " & car.year)
        Console.WriteLine("Lines: ")
        For Each ln As jsonCarLines In car.lines
            Console.WriteLine("    Name: " & ln.line)
            Console.WriteLine("    Engine: " & ln.engine)
            Console.WriteLine("    Color: " & ln.color)
            Console.WriteLine()
        Next
        Console.ReadLine()
    End Sub

End Module

我猜这可能需要一个自定义的 JsonConverter,但我对如何设置它有点不知所措。

最佳答案

以下是获取 SingleOrArrayConverter 的方法链接中的解决方案duplicate question为您的用例工作。

首先,这里是VB翻译的转换器代码。将其保存到项目中某处的类文件中。然后,您可以轻松地将其重用于任何类似的 future 案例。

Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq

Public Class SingleOrArrayConverter(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

现在你有了这个转换器,任何时候你有一个可以是列表或单个项目的属性,你所要做的就是在你的类中将它声明为一个列表,然后用 JsonConverter 注释该列表。属性使其使用 SingleOrArrayConverter类(class)。在你的情况下,这看起来像这样:
Public Class jsonCar
    Public Property make As String
    Public Property model As String
    <JsonConverter(GetType(SingleOrArrayConverter(Of jsonCarLines)))>
    Public Property lines As List(Of jsonCarLines)
    Public Property year As String
End Class

然后,像往常一样反序列化,它会按预期工作。
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)

这是一个完整的演示:https://dotnetfiddle.net/msYNeQ

关于json - 如何反序列化可以是数组或单个对象的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28395700/

相关文章:

json.net - `JsonConvert.DeserializeObject<Model>("{ float : NaN} ")` fails

c# - 反序列化动态属性列表

javascript - 如果 css() == X,否则,不工作,表单不工作

java - Elasticsearch - 默认情况下不映射字段

c# - 内联定义和声明

mysql - 单击按钮即可运行两个或多个查询

c# - 将 JSON 对象转换为 Data.Entities.Models.MyModel

json - Play 2.x Json 将 json 键从下划线大小写转换为驼峰式大小写

javascript - 从 Javascript 文件获取 JSON 数据

vb.net - 从数据库中检索图像