How to deserialize JSON, which can be an array or a single object

I am new to using JSON.net and have problems with some json that I get when it comes as an array, and sometimes as a single object. Here is an example of what I see using json

One of the ways he comes ...

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

Another way he can come in

{
  "Make": "Dodge",
  "Model": "Charger",
  "Lines": {
    "line": "base",
    "engine": "v6",
    "color": "red"
  },
  "Year": "2013"
}

Here is what I used for code that works on the first path and throws an exception in the second case. I comb through the network in order to realize this and really got stuck.

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

I assume that this will probably require a custom JsonConverter, but I don't understand a bit how to set this up.

+4
source share
4 answers

SingleOrArrayConverter , .

-, VB-. - . , .

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. :

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

+3

, jsonCar,

Public Class jsonCar
    Public Property make As String 
    Public Property model As String
    Public Property linesCollection As List(Of jsonCarLines) // Change name
    Public Property lines As String // Change the type to string
    Public Property year As String
End Class

:

Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)

If (car.lines.StartsWith("[")) Then
    car.linesCollection = JsonConvert.DeserializeObject(List(Of jsonCarLines))(car.lines)
Else
    car.linesCollection = new List(Of jsonCarLines)
    car.linesCollection.Add(JsonConvert.DeserializeObject(Of jsonCarLines)(car.lines))
EndIf
0

, , . JArray JObject . , , .

    Module Module1

    Sub Main()
     Dim jsonWithArray As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
     Dim jsonWithObject As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""base"",""engine"": ""v6"",""color"":""red""},""Year"":""2013""}"

     Dim witharray As Newtonsoft.Json.Linq.JObject = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonWithArray)
     Dim withstring As Newtonsoft.Json.Linq.JObject = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonWithObject)

     Dim jtokArray As Newtonsoft.Json.Linq.JToken = witharray("Lines")
     Dim jtokStr As Newtonsoft.Json.Linq.JToken = withstring("Lines")

     If (jtokArray.GetType() Is GetType(Newtonsoft.Json.Linq.JArray)) Then
        Console.WriteLine("its an array")
     End If

     If (jtokStr.GetType() Is GetType(Newtonsoft.Json.Linq.JObject)) Then
        Console.WriteLine("its an object")
     End If

    Console.ReadKey()

    End Sub

End Module
0

, . -, json. .

Public Class jsonCar
    Public Property make As String
    Public Property model As String
    Public Property linesArray 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 obj As JObject = JsonConvert.DeserializeObject(json)
        Dim ln As JToken = obj("Lines")

        Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)

        If (ln.GetType() Is GetType(Newtonsoft.Json.Linq.JArray)) Then
            car.linesArray = JsonConvert.DeserializeObject(Of List(Of jsonCarLines))(JsonConvert.SerializeObject(ln))
        End If

        If (ln.GetType() Is GetType(Newtonsoft.Json.Linq.JObject)) Then
            car.linesArray = New List(Of jsonCarLines)
            car.linesArray.Add(JsonConvert.DeserializeObject(Of jsonCarLines)(JsonConvert.SerializeObject(ln)))
        End If

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

End Module

. -, , .

0

All Articles