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 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
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.
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 )
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
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.