JSON Array not converting properly

Hi,

I am trying to convert from a list into JSON Array. Its working, but why the item is not shown properly.
I have 2 Rows, but its only converting 1 rows only.

Var Person As New JSONItem

Person.Value("no") = "auto"
Person.Value("dt") = "09/03/2022 00:00"
Person.Value("locCode") = "ASBH"
Person.Value("custCode") = "RTL"
Person.Value("ptypeCode") = "EDC"
Person.Value("ptermCode") = "CASH"
Person.Value("cashier") = "100"
Person.Value("remark") = "test API"
Person.Value("sourceTransId") = ""
Person.Value("incTax") = "true"

Var Kids As New JSONItem

dim i as integer
for i = 0 to Listbox1.ListCount-1
  'Kids.value(Listbox1.cell(i,0))=Listbox1.cell(i,1)
  Kids.value("itemcode")=Listbox1.cell(i,0)
  Kids.value("description")=Listbox1.cell(i,1)
  Kids.value("qty")=Listbox1.cell(i,2)
  Kids.value("itemprice")=Listbox1.cell(i,3)
  Kids.value("unitId")=""
  Kids.value("discount")="0"
  Kids.value("discountId")=""
  Kids.value("taxId")=""
next

Person.Value("items") = Kids

Person.Compact = True
Var s As String = Person.ToString

fldJSON.Text = s

fldJSONOut.Text = ""


try
  
  dim j1 as new JSONItem( fldJSON.Text )
  j1.Compact = cbCompact.Value
  fldJSONOut.Text = fldJSON1.text+EndOfLine+j1.ToString+EndOfLine+"DATA"
  
  
catch err as RuntimeException
  
  fldJSONOut.Text = "Error: " + EndOfLine
  fldJSONOut.AppendText err.Message
  fldJSONOut.AppendText EndOfLine
  fldJSONOut.AppendText str( err.ErrorNumber )
  
end try

the results comes only one rows,

any helps?

thanks
regards,
arief

The problem is you are only making one Kids object. You need to make multiple of them and add them into an Array, like this:

Var Kids() As JSONItem // an array of JSONitems

dim i as integer
for i = 0 to Listbox1.ListCount-1
  var K as new JSONItem  // each loop, we must create a new object

  K.value("itemcode")=Listbox1.cell(i,0)
  K.value("description")=Listbox1.cell(i,1)
  K.value("qty")=Listbox1.cell(i,2)
  K.value("itemprice")=Listbox1.cell(i,3)
  K.value("unitId")=""
  K.value("discount")="0"
  K.value("discountId")=""
  K.value("taxId")=""

  // add the newly created Kid to the array
  Kids.append K
next

Person.Value("items") = Kids  // set the array to the parent JSONItem
2 Likes

hi,
thanks for the help.
but I got an error Invalidargument exception if the kids is define as an array

error comes from this line code.

Person.Value("items") = Kids  // set the array to the parent JSONItem

I am using 2021. r1.1

thanks
regards,
Arief

I’m not seeing that - here’s a very simple test which compiles fine:

Var Person As New JSONItem
Var Kids() As JSONItem // an empty array of JSONitems
Person.Value("items") = Kids  // set the array to the parent JSONItem

Are you sure you don’t have a syntax error or something else?

What Xojo version are you using?

I get the same error. Changing

Var Kids() As JSONItem

to

Var Kids As New JSONItem

works correctly. Xojo 2021r3.1

now its working fine on 2021 r1.1

thanks for all the help

This is not how it should be done with JSONitems as the ts has found out.

You need a jsonitem that acts as an array:
New JSONItem("[]") // Force array
and use .Add on that to add json types (string, int, jsonitem etc) to that.

1 Like

Ok, looks like there is some confusion here due to a mix of API1 and API2, as well as my mistake with the Array.

While JSONItem will handle a Dictionary, including a Dictionary which includes an Array, JSONItem does not handle an actual array of JSONItems.

This seems like an oversight; I’ve submitted a Feature Request:
<https://xojo.com/issue/68214>
68214 - Array of JSONItems should auto convert to JSONItem Array

It’s pretty easy to write an extension method to do this (in fact, I think I had done this in other projects, which is why I thought it would work!)

I’d rather people just switch to using Dictionary and Variant(), then GenerateJSON to create the string. That’s what JSONItem (now) does on the backend anyway.

The same code:

Var Person As New Dictionary
...
Var Kids() As Variant // an array of kid objects

dim i as integer
for i = 0 to Listbox1.ListCount-1
  var K as new Dictionary  // each loop, we must create a new object

  K.value("itemcode")=Listbox1.cell(i,0)
  K.value("description")=Listbox1.cell(i,1)
  K.value("qty")=Listbox1.cell(i,2)
  K.value("itemprice")=Listbox1.cell(i,3)
  K.value("unitId")=""
  K.value("discount")="0"
  K.value("discountId")=""
  K.value("taxId")=""

  // add the newly created Kid to the array
  Kids.append K
next

Person.Value("items") = Kids  // set the array to the parent
Var s As String = GenerateJSON( Person )
1 Like

only xojo returns there an Object() array instead of a Dictionary() Array (which would be easier to handle)

And if using DesktopListbox, the code looks slightly different (ListCount → RowCount, and Cell → CellTextAt )

for i = 0 to Listbox1.RowCount-1
var K as new Dictionary

K.value("itemcode")=Listbox1.CellTextAt(i,0)
K.value("description")=Listbox1.CellTextAt(i,1)
K.value("qty")=Listbox1.CellTextAt(i,2)
K.value("itemprice")=Listbox1.CellTextAt(i,3)

A demo of the style I prefer, using the proper object ignoring how it’s implemented:

Var Person As New JSONItem

Person.Value("no") = "auto"
Person.Value("cashier") = "100"
//...

Var Kids As New JSONItem("[]") // a JSON item to hold an array for kid objects

For i As Integer = 0 to 2
  
  Var kid as new JSONItem  // Create a kid JSON object
  
  kid.value("itemcode") = i.ToText
  kid.value("description") = "Descr #" + i.ToText
  //...
  
  Kids.append kid // add the newly created Kid to the JSON array
  
Next

Person.Value("items") = Kids  // set the array to the items property of Person

Var s As String = Person.ToString // here is the Person object JSON string

break

I get the same results with:

Var Kids As New JSONItem("[]")

and

Var Kids As New JSONItem

at least with Xojo 2021r3.1. I think using ("[]") make it clear that we will use Add/Append because it will be an array, the question I have: is there any other difference?

Not presetting it as Array pass the job of guessing if the future structure will be a collection (or map, or dictionary, of properties) or an array to an analyzer inspecting the first content being inserted. I just preferred to inform beforehand and skip this guessing phase.

1 Like

Thank you Rick, I did some tests removing the for … next.
With JSONItem("[]") the value of s is:

{"no":"auto","cashier":"100","items":[]}

with JSONItem alone, the value of s is:

{"no":"auto","cashier":"100","items":{}}

this difference may be something that we need to consider. Thanks.

1 Like