Defined a method Operator_Convert for a simple class, to serialize it to a JSONItem:
Function Operator_Convert() As JSONItem
dim recipient as new JSONItem
recipient.Value("user_id") = userID
recipient.Value("is_read") = isRead
return recipient
End Function
this JSONItem need to be part of an array in another JSONItem
so doing this I get an IllegalCastException:
dim n as new MyClass
dim j as new JSONItem
j.append(JSONItem(n))
while doing this it works
dim n as new MyClass
dim j as new JSONItem
j.append(n.Operator_Convert)
this also works
dim n as new MyClass
dim j as new JSONItem
dim tempJSON as JSONItem = n
j.append(n)
Why it’s not possible to cast it to force the Operator_Convert method in a class?
Thats not what casting does
Its more like “treat this as if its one of these” rather than “if you can convert yourself to one of these”
No conversion is done which is what you’d need
Why not just use this which seems the most straight forward & simple & you say works
In fact this doesn’t work, and it’s not what I wrote.
This works:
dim n as new MyClass
dim j as new JSONItem
dim tempJSON as JSONItem = n
j.append(n)
Basically I have to temporarily assign the my class to a JSONItem property to let the Operator_Convert to work.
This is due JSONItem.Append() accept a Variant.
Why use Operator_Convert for this? Operator_Convert is usually used for object creation (as a replacement for New and the constructor). I’d use a method which clearly indicates the creation of an object:
Function Create() As JSONItem
dim recipient as new JSONItem
recipient.Value("user_id") = userID
recipient.Value("is_read") = isRead
return recipient
End Function
and:
Dim n As New MyClass()
Dim j As New JSONItem()
j.Append(n.Create)
If the Operator_Convert method is used elsewhere you could redirect the call from Create instead of deleting it:
Function Create() As JSONItem
return self.operator_Convert
End Function
[quote=252005:@Massimo Valle]In fact this doesn’t work, and it’s not what I wrote.
This works:
dim n as new MyClass
dim j as new JSONItem
dim tempJSON as JSONItem = n
j.append(n)
Basically I have to temporarily assign the my class to a JSONItem property to let the Operator_Convert to work.
This is due JSONItem.Append() accept a Variant.[/quote]
That makes no sense since you never use tempJSON
So you assign the results of operator_convert to just throw it away
Unless thats not really the code you use
And it wont be whats added to the json item array anyway
The issue you’re likely running into is that jsonItem.Append takes a variant and appends it to a jsonItem ARRAY (not sure thats what you want either)
That wont invoke the operator_convert
It just appends the object directly to the json array
Norman, my code was wrong, sorry.
This is the working one
dim n as new MyClass
dim j as new JSONItem
dim tempJSON as JSONItem = n
j.append(tempJSON)
and it’s the only way, because doing as you said
dim n as new MyClass
dim j as new JSONItem
j.append(n)
the j object silently append the object n as String, because MyClass has two Operator_Convert, one for converting it to a JSONObject and one for converting it to a String. And it takes the String one.
Doing n.toString I get a JSONException (11) for an Unrecognized object.
I believe the JSONItem.Append should check the object immediately instead of accepting it silently.
It gets the Operator_Convert As String, just tested.
In fact, when I try to convert the JSONItem to string I get a JSONException with a string reported:
Norman I double checked and yes you are right, the object is appended to the JSONItem.
Now, I believe the JSONItem.Append should only accept JSONItem instead of Variant.
Also even accepting a Variant, it should refuse any object other than JSONItem. What’s the meaning of appending any kind of object here?
In the end, the biggest problem is the JSONItem class silently accept any object, but then it fails when it’s time to serialize the JSONItem to string.
Then it should probably check the appended items are valid.
From the LR: “Values can be any of the following types: Strings, numbers, JSONItems, arrays, Booleans, or Nil.”
Would be nice if JSONItem.Value() would raise an exception if the assigned can’t be used.
Btw, there is still something I don’t understand, doing this:
dim person As New JSONItem
person.Value("date") = new Date
I get no error.
Then an exception is raised doing
dim s as string = person.toString
but the weird thing is the exception converted the date to a string (so it’s potentially a valid value), because it reports:
Meaning the JSONItem class is either wrong, because it has a string, or if it’s capable to recognize an invalid object assigned, it should complain when the value is assigned.
My point is the class should complain earlier about a wrong value or not complain at all
Also if the class has a string for my value, why complain at all, telling me a string is not a valid value?
Again: it is your duty to hand over only valid data types (as in Javascript for example).
Really? A Xojo date object is not a valid value to add to a JSONItem. It has to complain at some point…
Because it is a date object your adding to the JSONItem. There is no conversion done inside the JSONItem class, this is your job. That the debugger is showing it is something not related to a conversion happening. This is a debugger thing, showing a string representation of a date.
You could subclass JSONItem, override Value(name As String, Assigns value As Variant) and set its scope to “Private”. Then add the following methods:
Sub Value(name As String, Assigns value As Integer)
Super.Value(name) = value
End
Sub Value(name As String, Assigns value As Double)
Super.Value(name) = value
End
Sub Value(name As String, Assigns value As Boolean)
Super.Value(name) = value
End
Sub Value(name As String, Assigns value As JSONItem)
Super.Value(name) = value
End
Sub Value(name As String) // Set to null
Super.Value(name) = Nil
End
Anyway is not the debugger converting it to a string. I copied and pasted from the message box shown from the exception.
This mean the JSONItem doesn’t like to use it to build the JSONString, but gladly convert it to string to show it in the exception message.