Jsonfile Load Array of class

Hello I want to save my data in a JSONFile. Data structure is basic for now Class Server with name as string. I can save my servers array with this code:

Var dictArray() As Dictionary
Var d As Dictionary

d = New Dictionary
d.Value("Servers") = ServersToJson
d.Value("Todos") = ""
dictArray.Add(d)


Var json As String
json = GenerateJSON(d)
System.DebugLog(json)

Var f As FolderItem
f = FolderItem.ShowSaveFileDialog("text/plain", "test.txt")

Try
  Var file As TextOutputStream
  file = TextOutputStream.Create(f)
  file.Encoding = Encodings.UTF8
  file.WriteLine(json)
  file.Close
Catch error As IOException
  MessageBox("Error: " + error.Message)
End Try

// ServerToJson
Var a() As String
For Each s As Model.Server in Servers
  a.Add(s.ToJson)
Next
Return a

But I don’t find how to load my servers from JsonFile. My Jsonfile look like this

{“Servers”:[“{"Name":"COM1"}”,“{"Name":"FR101"}”],“Todos”:“”}

With this code I have a TypeMismatchException

Var jsonData As String
Var f As FolderItem
f = FolderItem.ShowOpenFileDialog("text/plain")

Try
  Var file As TextInputStream
  file = TextInputStream.Open(f)
  file.Encoding = Encodings.UTF8
  jsonData = file.ReadAll
  file.Close
  System.DebugLog(jsonData)
Catch error As IOException
  MessageBox("Error: " + error.Message)
End Try

Var d As Dictionary
d = ParseJSON(jsonData)

var s() as JSONItem
s=ParseJSON(d.Value("Servers"))

Don’t mix JSONItem and dictionary. You’re shooting yourself in the foot.

Use exclusively Dictionary or exclusively JSONItem:

var js as new jsonitem(jsondata)
Var servers as JSONItem = js.child("servers")

Var c as integer = servers.count

For I as integer = 0 to c-1
    Var server as JSONItem = servers.childAt(i)
    Var name as string = server.Value("name")
Next
3 Likes

Also, after years of using dictionaries exclusively in maybe hundreds of methods, I can confidently say: use JSONItem. Handling arrays ranges from cumbersome to infuriating due to how Xojo handles arrays in variants.

5 Likes

I try your code with the right keys “Servers” and “Name”


Var js as new JSONItem(jsonData)
Var Servers as JSONItem = js.Child("Servers")

For i as integer = 0 to Servers.LastRowIndex
  Var server as JSONItem = servers.childAt(i)
  System.DebugLog(server.ToString)
  Var name as string = server.Value("Name")
Next

I got this output

14:27:34 : {"Servers":["{\"Name\":\"COM1\"}","{\"Name\":\"FR101\"}","{\"Name\":\"PTR3\"}"],"Todos":""}

         : "{\"Name\":\"COM1\"}"

And this error

Exception Message: JSONItem is an array

Exception Error Number: 13

It reads like your saving method is designed incorrectly. The array of server items is an array of strings containing JSON, not an array of JSONItems as it should be.

The JSON you’ve posted can be parsed, but it would be to your benefit to fix the saving method. If you post the saving code, someone could help with that and I think that would be the better resolution.

If you’re stuck with the JSON you’ve posted because something in the wild is generating that, it can be worked with. Construct a JSONItem from the String value of each item in the Servers array. I’m hesitant to give you something you can copy and paste (in an effort to encourage fixing this the right way).

1 Like

Thank you @Tim_Parnell . Can you help me with the save method?

Var dictArray() As Dictionary
Var d As Dictionary

d = New Dictionary
d.Value("Servers") = ServersToJson
d.Value("Todos") = ""
dictArray.Add(d)


Var json As String
json = GenerateJSON(d)

Var f As FolderItem
f = FolderItem.ShowSaveFileDialog("text/plain", "test.txt")

Try
  Var file As TextOutputStream
  file = TextOutputStream.Create(f)
  file.Encoding = Encodings.UTF8
  file.WriteLine(json)
  file.Close
Catch error As IOException
  MessageBox("Error: " + error.Message)
End Try

ServerToJson

Var j() As JSONItem
For Each s As Model.Server in Servers
  // ??
Next
Return j

JSONItem is always singular, unlike the Dictionary design.

ServerToJSON would become something similar to this:

var j as new JSONItem
for each s as Model.Server in Servers
  j.Add(jsItemRepresentingTheServer)

next s

return j

You should adjust the outer dictArray() thing to be a JSONItem as well, as Greg mentioned avoiding the mixture of the JSONItem and Dictionary approaches.

I have built a demo project that shows you how I usually build serializable class objects (with array handling!) when I’m not using a magic introspection base class.

You can check out my demo example here: https://tim.gdn/jzMH7

2 Likes