JSON Hierarcrhial Listbox puzzle

I have the below code in the “RowExpanded” event of a desktoplistbox. Ive also included the test json string. If I try the JSONItem method I cant for the life of me get this to work - xojo wont return a JSONItem from the .child(key) method?! It will not allow me cast the returned item, “_VariantString cannot be cast to JSONItem”:

The json string:

{
    "CustomerName": "Smithers",
    "number": "31158",
    "status": "WIP",
    "date": "2023-05-08 07:00:00",
    "quantity": 50,
    "length": 4,
    "description": "DCA 8 5/16 x 6 x 5",
    "code": "200kjkgjgjhgkhg",
    "width": 494,
    "assets":
    [
        "\\\\server\\Drive\\Afolder\\subfolder\\topic\\2023\\04\\04-28-2023\\12Print.pdf",
        "\\\\server\\Drive\\Afolder\\subfolder\\topic\\2023\\04\\04-28-2023\\13Print.pdf",
        "\\\\server\\Drive\\Afolder\\subfolder\\topic\\2023\\04\\04-28-2023\\14Print.pdf"
    ],
    "routes":
    [
        "First",
        "Second",
        "Third",
        "Fourth",
        "Fifth"
    ],
    "product": "DG",
    "specialinstructions": "kjhgghklhkhlklkhklh",
    "sequence": 1,
    "shippinginstructions": "THIRD PARTY BILLING - FEDEX 676767676 - ADDRESS SHIP FROM: ThePlace 8000 SOME AVENUE, VAN NUYS, CA 91406",
    "targetquantity": 
    [
        0,1,2,3,4,5
    ]
}

Heres the “RowExpanded” code I want to work:

var details as JSONItem = me.RowTagAt(row)
// ive also tried variant - no go
var info as JSONItem
for each k as string in details.Keys
  // this cast blows up
  info = details.Child(k)
  if info.IsArray then
    var j as new JSONItem
    var vals() as variant = JSONItem(info).Value(k)
    for m as integer = 0 to vals.count-1
      j.value(k)=vals(m)
    next
    me.AddExpandableRow(k)
    me.RowTagAt(me.LastAddedRowIndex)=j
  else
    me.AddRow(k  +  ":  " + str(JSONItem(info).Value(k)) )
  end if
next

Interestingly, a dictionary approach sort of works but you have to KNOW the arrray names:

// Dictionary Approach - have to know about array names?!?!?!
if me.RowTagAt(row) Isa JSONItem then
  var details as Dictionary = ParseJSON(JSONItem(me.RowTagAt(row)).ToString)
  for each info as DictionaryEntry in details
    if info.key="routes" or info.key="assets" or info.key="targetquantity" then
      var j as new JSONItem
      var vals() as Object = info.value
      for i as integer = 0 to vals.count-1
        j.Value(info.key+str(i))=vals(i)
      next
      me.AddExpandableRow(info.key)
      me.RowTagAt(me.LastAddedRowIndex)=j
    else
      me.AddRow(info.key + ":  " + str(info.Value))
    end if
  next
else
  
end if

How the heck can one iterate a JSONItem wihtout knowing or caring whats in there!?

For your Dictionary method you can use info.value.isarray e.g.

if me.RowTagAt(row) Isa JSONItem then
  var details as Dictionary = ParseJSON(JSONItem(me.RowTagAt(row)).ToString)
  for each info as DictionaryEntry in details
    if info.value.IsArray then
      var j as new JSONItem
      var vals() as Object = info.value
      for i as integer = 0 to vals.count-1
        j.Value(info.key+str(i))=vals(i)
      next
      me.AddExpandableRow(info.key)
      me.RowTagAt(me.LastAddedRowIndex)=j
    else
      me.AddRow(info.key + ":  " + str(info.Value))
    end if
  next
else
  
end if

You can’t. That’s the dirty secret of both xml and json. You really have to know what to expect.

1 Like

Bravo Wayne! You’re the man! I knew there was a way but I was too close to it! Now, in the am, what about if theres another object in there?