skip to Main Content

I’m trying to parse a big JSON and I only need few things from it.
I’ve been trying to beautify it but I’m having trouble also because it seems that’s not completely correct.
This is the website
and I’ve tried to delete all the unnecessary json
ending up with

[
   [
      "updateGlobalData",
      {
         "backgroundData":{
            "cities":[
               {
                  "type":"city",
                  "name":"Polis",
                  "id":186979,
                  "level":35,
                  "ownerId":"99253",
                  "ownerName":"D3vil666",
                  "ownerAllyId":"0",
                  "hasTreaties":0,
                  "actions":[
                     
                  ],
                  "state":"vacation",
                  "viewAble":1,
                  "infestedByPlague":false
               },
               {
                  "type":"city",
                  "name":"London",
                  "id":378440,
                  "level":28,
                  "ownerId":"242906",
                  "ownerName":"Mattia",
                  "ownerAllyId":"5541",
                  "ownerAllyTag":"LORDS",
                  "hasTreaties":0,
                  "actions":[
                     
                  ],
                  "state":"",
                  "viewAble":2,
                  "infestedByPlague":false
               }
            ]
         }
      }
   ]
]

The properties I’m looking for are "State" and "ownerName".
State can be "vacation" like ""state"": ""vacation"" or "" like ""state"": """"
These properties are often repeated so I’m only looking for to parse them only once.
For example:
I want to know which state Mattia has and it should return "nothing".
Which state D3vil666 has and it should return "vacation".

The code I’m using:

Public Class Form1

    Public Class GlobalData
        Public Class BackgroundData
            Public Property Cities As List(Of City)
        End Class

        Public Class City
            Public Property Type As String
            Public Property Name As String
            Public Property OwnerName As String
            Public Property State As String
        End Class

        Public Property BackgroundDataa As BackgroundData
    End Class

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim client As New WebClient()
        Dim jsonString As String = client.DownloadString("https://s10-it.ikariam.gameforge.com/?view=updateGlobalData&islandId=1649&backgroundView=island&currentIslandId=1649&actionRequest=90983fef22b312ff7cbd51f0183bc301&ajax=1")

        Dim data As List(Of GlobalData) = JsonConvert.DeserializeObject(Of List(Of GlobalData))(jsonString)
        Dim state = data(0).BackgroundDataa.Cities.FirstOrDefault(Function(x) x.OwnerName = "Mattia").State
        MsgBox(state)
    End Sub
End Class

but I’m getting the error:

Newtonsoft.Json.JsonSerializationException: ‘Cannot deserialize the current JSON array (e.g. [1,2,3]) into type ‘Ikariam_VM.Form1+GlobalData’ because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path ‘[0]’, line 1, position 2.’

I’m working on winform App for .net6+ and using the nuget Newtonsoft package to handle the json.

Any idea?
Thanks

edit1:

Code after suggestions

Imports System.Net
Imports System.Net.Http
Imports System.Net.WebRequestMethods
Imports System.Runtime.InteropServices.JavaScript.JSType
Imports System.Text.Json
Imports Microsoft.Web.WebView2.Core
Imports Microsoft.Web.WebView2
Imports Microsoft.Web.WebView2.WinForms
Imports System.Threading
Imports System.IO
Imports System.Runtime.InteropServices.JavaScript
Imports Newtonsoft.Json.Linq
Imports Newtonsoft.Json

Public Class Form1



    Public Class GlobalData
        Public Class BackgroundData
            Public Property Cities As List(Of City)
        End Class

        Public Class City
            Public Property Type As String
            Public Property Name As String
            Public Property OwnerName As String
            Public Property State As String
        End Class
    End Class
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim client As New WebClient()
            Dim jsonString As String = client.DownloadString("https://s10-it.ikariam.gameforge.com/?view=updateGlobalData&islandId=1649&backgroundView=island&currentIslandId=1649&actionRequest=90983fef22b312ff7cbd51f0183bc301&ajax=1")

            Dim jArr = JArray.Parse(jsonString)

            Dim cities = TryCast(jArr(0).OfType(Of JObject)() _
                   .Select(Function(p) p.Properties().Where(Function(p) p.Name = "backgroundData").First()) _
                   .FirstOrDefault().Value("cities"),
                 JArray)

            Dim state As String = Nothing

            If cities IsNot Nothing Then
                state = CStr(cities.Where(Function(c) CStr(c("OwnerName") = "D3vil666")) _
                           .FirstOrDefault()("state"))
            End If
        End Sub
    End Class

2

Answers


  1. You don’t need any custom classes to get data you need from a json string you posted. I haven’t a VB.Net compillator so I post my code in c#. I hope you will find somebody to tranclate it to VB.Net

        var jArr = JArray.Parse(json);
    
        var cities = jArr[0].OfType<JObject>()
                       .Select(p => p.Properties().Where(p => p.Name == "backgroundData").First())
                       .FirstOrDefault().Value["cities"] as JArray;
                       
        string state=null;
        
        if (cities != null)
            state = (string)cities.Where(c => (string)c["ownerName"] == "D3vil666")
                             .FirstOrDefault()["state"]; // "vacation"
    
    Login or Signup to reply.
  2. Serge’s answer, translated into VB:

    Dim jArr = JArray.Parse(json)
    
    Dim cities = TryCast(jArr(0).OfType(Of JObject)() _
                   .Select(Function(p) p.Properties().Where(Function(q) q.Name = "backgroundData").First()) _
                   .FirstOrDefault().Value("cities"),
                 JArray)
    
    Dim state As String = Nothing
    
    If cities IsNot Nothing Then
        state = CStr(cities.Where(Function(c) CStr(c("OwnerName") = "D3vil666")) _
                           .FirstOrDefault()("state"))
    End If
    

    I think this is a spot where VB still needs the continuation characters to handle the lines properly.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search