Expected String() but got Variant()

Good afternoon (o;

I have a JSON backend where I get visit status from our online shop system.
As a test I have set up a simple DesktopListBox with four columns.

So when the JSON is returned and HTTP status is 200 then I process it like:

Var jsonDict As Dictionary = ParseJSON(s)
Var visits() As Variant = jsonDict.Value("data")

TextArea1.AddText("Dict count: " + Str(visits.Count) + EndOfLine)

For Each visit As Dictionary In visits
  Var columns() As String = Array(visit.Value("Zeit"), visit.Value("ID"), visit.Value("Artikel"), visit.Value("Preis"))
  ListBox1.AddRow(columns)
Next

Now what is odd that the last visit.Value in building the String() throws this exception.
But as soon I replace it with a static String like:

Var columns() As String = Array(visit.Value("Zeit"), visit.Value("ID"), visit.Value("Artikel"), "")

It works


Tried then with building a String array of size five like:

Var columns() As String = Array(visit.Value("Zeit"), visit.Value("ID"), visit.Value("Artikel"), visit.Value("Preis"), "")

And this works fine as well, though the last column isn’t used in the DesktopListBox.

When building the array, be specific by using StringValue, e.g., = Array(visit.Value("Zeit").StringValue, ...

Likely the last value is nil which cannot be used in a string array, StringValue will convert that to an empty string for you.

But if I add an empty String after visit.Value(“Zeit”) then it is accepted as String().

So visit.Value(“Zeit”) isn’t Nil


I was speculating. Regardless, use StringValue as I suggested and it should work.

The reason is the Array() construct creates an array of whatever variable type the first value is. Since you’re using Dictionary.Value you get an array of Variant. By using Variant.StringValue you are converting from Variant to String and so the array will be String() instead. If don’t use StringValue on all of them, you’ll get an error since every member of the array needs to be the same type. Array() will not do any type conversion for you.

2 Likes

Interesting (o;

I just need the last element to convert to avoid the error:

Var columns() As String = Array(visit.Value("Zeit"), visit.Value("ID"), visit.Value("Artikel"), visit.Value("Preis").StringValue)

So I believe it just actually takes the last element to check if it is of type String


Did you try using .StringValue only on the first element?

You’re right (o;

Just one element needs .StringValue, regardless which position


Good catch :wink:

1 Like

Looks like using only 1 .StringValue in the Array works the same as putting on all of them. At least using OP’s code.

Wait a minute


Does it mean I found another bug in Xojo? (o;

So that at least one element has to be of type String to pass the compile?

Perhaps when the runtime is first presented with a string, it changes the destination variant array into a string array. Thereafter all the strings just go in with no conversion needed.

Is a feature. As you are setting one of the Variants to String, then that sets the type for the array. The compiler now does not have to guess what to do with other variants. (My guess).

Edit: right, runtime not compile.

This is a runtime action, not a compile time one.

1 Like

I don’t know the difference. When I run, no compilation/build is done? It says ‘compiling’ when I run.
Can I get no error at runtime but then get errors at build time?

If you get errors at buildtime, the run stage is not reached. When you run in the IDE, the program is compiled and built, else how could it run? Clicking Build just gets you an executable that you run later.

Unless the program is a script (not the case here), there is always a compile-build-run chain. This is true whether you click “Run” or whether you click “Build”.

Edit: You can have errors a compile time, such as syntax error. You can have errors at build time, such as missing library. Then you can have errors at run time, such as I/O exception. The compiler only catches the first of these.