Iterating through JSON object in Xojo

I have a JSON object, not array, that is structured like:

{
"0100010000":{
    "CommandStr":"SceneComment\/Comment1",
    "MaxCh":0,
    "MinVal":0,
    "MaxVal":0,
    "DefVal":0,
    "Command":"0100010000",
    "ChType":"ch",
    "ValType":"x10",
    "Hide":false
  },
  "0100010001":{
    "CommandStr":"SceneComment\/Comment2",
    "MaxCh":0,
    "MinVal":0,
    "MaxVal":0,
    "DefVal":0,
    "Command":"0100010001",
    "ChType":"ch",
    "ValType":"x10",
    "Hide":false
  }
}

I can’t figure out how to iterate through the structure. I’d like to load a listbox with the values, using the names as column headings.
I can get the count of the main objects, which gives me the rows, but I can’t seem to figure out how to iterate through the sub-objects. I’m sure it’s some combination of JSON.Child, JSON.Name and JSON.Value formula, but I can’t seem to get the syntax just right. If it were an array, it’d be easy!


Dim j As New JSONItem(somejson)


For Each name As String In j.names
  
  Dim node As jsonItem = j.child(name)
  
  textarea1.AppendText name + EndOfLine
  
  // now walk through the items in this node
  
  For Each subnames As String In node.names
    
    //Dim subnode As jsonitem = node.child(subnames)
    
    textarea1.AppendText "     " + subnames + EndOfLine
    
  Next
  
Next
1 Like

Ah! I didn’t think of using For Each. Very nice.
Thank you, Norm!!

“Dictionary cannot be cast to JSONItem”

JSON is my “j” in this case

For Each name As String In JSON.Names
  Dim node As JSONItem = JSON.Child(name)
  System.DebugLog("Name = " + name)
  For Each subname As String In node.names
    System.DebugLog("  Subname = " + subname)
  Next
Next

variable declarations would be useful to see
and what version are you using ?
I wrote mine in 2019r1.1 and ran it so I know it works in that version
I just defined a constant named someJson with your json in it

I’m loading the JSON object via a Dictionary. My first foray into JSON in Xojo, so likely I could do this better. The JSON is created from a csv.
It’s a lot of code, but I’ll post what I think might be relevant, let me know if you need more?

Dim cmd As String
Dim JSONDict As Dictionary
JSON = New JSONItem // Window property...
JSON.Compact = False
    
JSONDict = New Dictionary

For i As Integer = 1 to 20 // obviously all elements will be equal in this case...
    cmd = "1010101010"
    JSONDict.Value("CommandStr") = "somecommand"
    JSONDict.Value("MaxCh") = 10
    JSONDict.Value("MinVal") = 0
    JSONDict.Value("MaxVal") = 100
    JSONDict.Value("DefVal") = 10
    JSONDict.Value("Command") = cmd
    JSONDict.Value("ChType") = "ch"
    JSONDict.Value("ValType") = "%"
    JSONDict.Value("Hide") = False
    
    //JSON.Append(JSONDict) // As Array
    JSON.Value(Cmd) = JSONDict // As Object by Command Hex value
  
Next i

For Each name As String In JSON.Names
  Dim node As JSONItem = JSON.Child(name)
  System.DebugLog("Name = " + name)
  For Each subname As String In node.names
    System.DebugLog("  Subname = " + subname)
  Next
Next

System.DebugLog(JSON.ToString)

I probably don’t even need a dictionary. Is that what’s causing the error?

I think I used a Dictionary initially as I thought that was the “right way” but as things changed, I don’t know that I need one anymore?

ah youre shoving an entire dictionary in there
not json :slight_smile:

so the accessor

Dim node As JSONItem = myJSON.Child(name)

blows up with an exception
try this
all I did was replace the Dictionary with a Jsonitem

Dim node As JSONItem = myJSON.Child(name)
``` isnt getting a jsonitem node its getting a dictionary and then we get an illegal cast exception :slight_smile:

its the different between how you're constructing the json vs how I did it
  
```xojo
Dim cmd As String

Dim myJSON As New JSONItem // Window property...
myJSON.Compact = False



For i As Integer = 1 To 20 // obviously all elements will be equal in this case...
  Dim newNode As New JsonItem
  
  cmd = "1010101010" + Str(i)
  newNode.Value("CommandStr") = "somecommand"
  newNode.Value("MaxCh") = Str(i) // 10
  newNode.Value("MinVal") = 0
  newNode.Value("MaxVal") = 100
  newNode.Value("DefVal") = Str(i) // 10
  newNode.Value("Command") = cmd
  newNode.Value("ChType") = "ch"
  newNode.Value("ValType") = "%"
  newNode.Value("Hide") = False
  
  //JSON.Append(JSONDict) // As Array
  myJSON.Value(Cmd) = newNode // As Object by Command Hex value
  
Next i

System.DebugLog(myJSON.ToString)

For Each name As String In myJSON.Names
  Dim node As JSONItem = myJSON.Child(name)
  System.DebugLog("Name = " + name)
  For Each subname As String In node.names
    System.DebugLog("  Subname = " + subname)
  Next
Next

Sounds like we came to same conclusion simultaneously. Get rid of the Dictionary and use straight JSON. Lemme try that and see what happens.

That was it! Funny that when outputting the final JSON, even though each row is a dictionary, it comes out properly. I erroneously assumed that once you do JSON = DICTIONARY, the dictionary is parsed into a JSON, and is no longer a dictionary… :wink:

The illegal cast exception is what clued me in
Since you assign a “variant” (the only way to do some things in Xojo given how it works today) you get back a variant - in this case your dictionary
That JSONItem.ToString walked the dictionary is … perhaps a bug since a json item SHOULD only contain EITHER key value pairs OR jsonitems - not dictionaries

I could be wrong about this but that seems wrong that you can shove a dict in and it doesnt touch it OR converts it to string … not sure which

1 Like