Why not something like this . Maybe you should provide an example if I am not addressing your question correctly:cast a Map object to a Custom type object that has the same fields.
Sub Class_Globals
Private Root As B4XView
Private xui As XUI
Type maptocustom(mymap As Map)
End Sub
Public Sub Initialize
' B4XPages.GetManager.LogEvents = True
End Sub
'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Dim mp As Map
mp.Initialize
mp=CreateMap("name":"Mike", "city":"Roma", "country":"Italia")
Dim mc As maptocustom = Createmaptocustom (mp)
Dim x As Map = mc.mymap
For Each s As String In x.Keys
Log($"${s} ${x.Get(s)}"$)
Next
End Sub
Public Sub Createmaptocustom (mymap As Map) As maptocustom
Dim t1 As maptocustom
t1.Initialize
t1.mymap = mymap
Return t1
End Sub
Hi, thanks for your interest, actually what I was looking for is something similar to Java and PythonWhy not something like this . Maybe you should provide an example if I am not addressing your question correctly:
B4X:Sub Class_Globals Private Root As B4XView Private xui As XUI Type maptocustom(mymap As Map) End Sub Public Sub Initialize ' B4XPages.GetManager.LogEvents = True End Sub 'This event will be called once, before the page becomes visible. Private Sub B4XPage_Created (Root1 As B4XView) Root = Root1 Dim mp As Map mp.Initialize mp=CreateMap("name":"Mike", "city":"Roma", "country":"Italia") Dim mc As maptocustom = Createmaptocustom (mp) Dim x As Map = mc.mymap For Each s As String In x.Keys Log($"${s} ${x.Get(s)}"$) Next End Sub Public Sub Createmaptocustom (mymap As Map) As maptocustom Dim t1 As maptocustom t1.Initialize t1.mymap = mymap Return t1 End Sub
Dim mp As Map
mp.Initialize
mp=CreateMap("Name":"Mike", "City":"Roma", "Country":"Italia")
Type User(Name as String, City As String, Country As String)
dim u as User
u = mp
dim u as User
u = mp.As(User)
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Root.LoadLayout("MainPage")
'In Class_Globals: Type MyType(Name As String, City As String, Country As String)
' hover over 'MyType to generate CreateMyType, replace arguments as shown below
Dim Person1 As MyType = CreateMyType(CreateMap("Name":"Mike", "City":"Roma", "Country":"Italia"))
Log(Person1.Name & TAB & Person1.City & TAB & Person1.Country)
End Sub
Public Sub CreateMyType(mp As Map) As MyType
Dim t1 As MyType
t1.Initialize
t1.Name = mp.Get("Name")
t1.City = mp.Get("City")
t1.Country = mp.Get("Country")
Return t1
End Sub
No, they are distinct types.I was wondering if it possibile to cast a Map object to a Custom type object that has the same fields.
Yes this is what I've done , I was wondering if there was something "elite" to do the casting, but the answer seems to be no unfortunatelyHow about this?
B4X:Private Sub B4XPage_Created (Root1 As B4XView) Root = Root1 Root.LoadLayout("MainPage") 'In Class_Globals: Type MyType(Name As String, City As String, Country As String) ' hover over 'MyType to generate CreateMyType, replace arguments as shown below Dim Person1 As MyType = CreateMyType(CreateMap("Name":"Mike", "City":"Roma", "Country":"Italia")) Log(Person1.Name & TAB & Person1.City & TAB & Person1.Country) End Sub Public Sub CreateMyType(mp As Map) As MyType Dim t1 As MyType t1.Initialize t1.Name = mp.Get("Name") t1.City = mp.Get("City") t1.Country = mp.Get("Country") Return t1 End Sub
'This sub creates all the code needed and places it on the log
'To use, just once then comment:
' GenerateCustomType("MyType", CreateMap("Name":"Mike", "City":"Roma", "Country":"Italia", "Amount": 1000000))
Private Sub GenerateCustomType(typeName As String, mp As Map)
Dim sb As StringBuilder: sb.Initialize
sb.Append("'Place this line in Globals").Append(CRLF)
sb.Append("'").Append(TAB).Append("Type ").Append(typeName).Append("(")
For Each kw As String In mp.Keys
Dim obj As Object = mp.Get(kw)
Dim typ As String = GetType(obj)
typ = typ.SubString(typ.LastIndexOf(".") + 1).trim
If typ = "Integer" Then typ = "Int"
sb.Append(kw).Append(" As ").Append(typ).Append(", ")
Next
If sb.Length > 1 Then sb.Remove(sb.Length - 2, sb.Length)
sb.Append(")").Append(CRLF)
sb.Append("'").Append(CRLF)
sb.Append("'").Append("Public Sub Create").Append(typeName).Append("(mp As Map) As ").Append(typeName).Append(CRLF)
sb.Append("'").Append(TAB).Append("Dim t1 As MyType").Append(CRLF)
sb.Append("'").Append(TAB).Append("t1.Initialize").Append(CRLF)
For Each kw As String In mp.Keys
sb.Append("'").Append(TAB).Append("t1.").Append(kw).Append(" = ").Append("mp.Get(").Append(QUOTE).Append(kw).Append(QUOTE).Append(")").Append(CRLF)
Next
sb.Append("'").Append(TAB).Append("Return t1").Append(CRLF)
sb.Append("'").Append("End Sub")
Log(sb.ToString)
End Sub
'On log:
'Place this line in Globals
' Type MyType(Name As String, City As String, Country As String, Amount As Int)
'
'Public Sub CreateMyType(mp As Map) As MyType
' Dim t1 As MyType
' t1.Initialize
' t1.Name = mp.Get("Name")
' t1.City = mp.Get("City")
' t1.Country = mp.Get("Country")
' t1.Amount = mp.Get("Amount")
' Return t1
'End Sub
Sub Class_Globals
Type MyType(Name As String, City As String, Country As String, _
Amount As Int, Grade As Float, Phones As List, TestMap As Map, TestArray() As Int)
End Sub
Private Sub B4XPage_Created (Root1 As B4XView)
'Run just once to put required Sub on the log, argument is direct copy of Type statement
GenerateCreateType($"
Type MyType(Name As String, City As String, Country As String, _
Amount As Int, Grade As Float, Phones As List, TestMap As Map, TestArray() As Int)
"$)
Dim Person1 As MyType = MyTypeFromMap(CreateMap("Name":"Mike", "City":"Roma", "Country":"Italia", _
"Amount": 1000000, "Grade": 2.5, "Phones": CreateList(Array(1111111111, 2222222222, 3333333333)), _
"TestMap": CreateMap("Member": "William"), "TestArray": Array As Int(1,2,3)))
Log(Person1.Name & TAB & Person1.City & TAB & Person1.Country & TAB & Person1.Amount & _
TAB & Person1.Grade & TAB & Person1.Phones.Size & TAB & Person1.testMap.Get("Member") & TAB & Person1.TestArray(2))
End Sub
Private Sub GenerateCreateType(s As String)
s = s.Replace(CRLF, " ").Replace(" _ ", " ") 'to combine multiline declaration
Dim v() As String = TwoParts("(", s.trim)
Dim tname As String = v(0).substring(v(0).IndexOf(" ")+ 1)
Dim sb As StringBuilder: sb.Initialize
Dim args() As String = Regex.Split("\,", v(1).substring2(0, v(1).Length - 1))
For i = 0 To args.Length - 1
v = IIf(args(i).IndexOf("(") > -1, TwoParts("(", args(i).trim), TwoParts(" ", args(i).trim))
sb.Append($"'${TAB}If mp.ContainsKey("${v(0)}") Then t1.${v(0)} = mp.Get("${v(0)}")${CRLF}"$)
Next
Dim s As String = $"
'Public Sub ${tname}FromMap(mp As Map) As ${tname}
' Dim t1 As ${tname}
' t1.Initialize
${sb.ToString}
' Return t1
'End Sub
"$
Log(s)
End Sub
Private Sub TwoParts(delim As String, s As String) As String()
s = s.trim
Dim result(2) As String
result(0) = s
Dim k As Int = s.IndexOf(delim)
If k > - 1 Then
result(0) = s.SubString2(0, k).trim
result(1) = s.SubString(k + delim.length).trim
End If
Return result
End Sub
Private Sub CreateList(ar() As Object) As List
Dim a As List
a.Initialize
For Each obj As Object In ar
a.Add(obj)
Next
Return a
End Sub
'Copied from log, generated by: GenerateCreateType
Public Sub MyTypeFromMap(mp As Map) As MyType
Dim t1 As MyType
t1.Initialize
If mp.ContainsKey("Name") Then t1.Name = mp.Get("Name")
If mp.ContainsKey("City") Then t1.City = mp.Get("City")
If mp.ContainsKey("Country") Then t1.Country = mp.Get("Country")
If mp.ContainsKey("Amount") Then t1.Amount = mp.Get("Amount")
If mp.ContainsKey("Grade") Then t1.Grade = mp.Get("Grade")
If mp.ContainsKey("Phones") Then t1.Phones = mp.Get("Phones")
If mp.ContainsKey("TestMap") Then t1.TestMap = mp.Get("TestMap")
If mp.ContainsKey("TestArray") Then t1.TestArray = mp.Get("TestArray")
Return t1
End Sub
'On Log
'Public Sub MyTypeFromMap(mp As Map) As MyType
' Dim t1 As MyType
' t1.Initialize
' If mp.ContainsKey("Name") Then t1.Name = mp.Get("Name")
' If mp.ContainsKey("City") Then t1.City = mp.Get("City")
' If mp.ContainsKey("Country") Then t1.Country = mp.Get("Country")
' If mp.ContainsKey("Amount") Then t1.Amount = mp.Get("Amount")
' If mp.ContainsKey("Grade") Then t1.Grade = mp.Get("Grade")
' If mp.ContainsKey("Phones") Then t1.Phones = mp.Get("Phones")
' If mp.ContainsKey("TestMap") Then t1.TestMap = mp.Get("TestMap")
' If mp.ContainsKey("TestArray") Then t1.TestArray = mp.Get("TestArray")
' Return t1
'End Sub
it is not what was I was looking for, but it is very cool the idea you hadIt is possible to do it the other way around, and it is more intuitive.
Start with the type statement and generate the MyTypeFromMap sub with the parser below.
I've added more bells and whistles and made it more robust.
The map can have more or less fields defined then the type.
I can see it working as follows. You have a map derived from a JSON file. There may be one or more custom types in there.
Run the GenerateCustomType for each type once in development (remove or comment when satisfied).
Then create and use the instances of each type. The code below is about 80 lines. The code generator itself is a dozen lines.
B4X:Sub Class_Globals Type MyType(Name As String, City As String, Country As String, _ Amount As Int, Grade As Float, Phones As List, TestMap As Map, TestArray() As Int) End Sub Private Sub B4XPage_Created (Root1 As B4XView) 'Run just once to put required Sub on the log, argument is direct copy of Type statement GenerateCreateType($" Type MyType(Name As String, City As String, Country As String, _ Amount As Int, Grade As Float, Phones As List, TestMap As Map, TestArray() As Int) "$) Dim Person1 As MyType = MyTypeFromMap(CreateMap("Name":"Mike", "City":"Roma", "Country":"Italia", _ "Amount": 1000000, "Grade": 2.5, "Phones": CreateList(Array(1111111111, 2222222222, 3333333333)), _ "TestMap": CreateMap("Member": "William"), "TestArray": Array As Int(1,2,3))) Log(Person1.Name & TAB & Person1.City & TAB & Person1.Country & TAB & Person1.Amount & _ TAB & Person1.Grade & TAB & Person1.Phones.Size & TAB & Person1.testMap.Get("Member") & TAB & Person1.TestArray(2)) End Sub Private Sub GenerateCreateType(s As String) s = s.Replace(CRLF, " ").Replace(" _ ", " ") 'to combine multiline declaration Dim v() As String = TwoParts("(", s.trim) Dim tname As String = v(0).substring(v(0).IndexOf(" ")+ 1) Dim sb As StringBuilder: sb.Initialize Dim args() As String = Regex.Split("\,", v(1).substring2(0, v(1).Length - 1)) For i = 0 To args.Length - 1 v = IIf(args(i).IndexOf("(") > -1, TwoParts("(", args(i).trim), TwoParts(" ", args(i).trim)) sb.Append($"'${TAB}If mp.ContainsKey("${v(0)}") Then t1.${v(0)} = mp.Get("${v(0)}")${CRLF}"$) Next Dim s As String = $" 'Public Sub ${tname}FromMap(mp As Map) As ${tname} ' Dim t1 As ${tname} ' t1.Initialize ${sb.ToString} ' Return t1 'End Sub "$ Log(s) End Sub Private Sub TwoParts(delim As String, s As String) As String() s = s.trim Dim result(2) As String result(0) = s Dim k As Int = s.IndexOf(delim) If k > - 1 Then result(0) = s.SubString2(0, k).trim result(1) = s.SubString(k + delim.length).trim End If Return result End Sub Private Sub CreateList(ar() As Object) As List Dim a As List a.Initialize For Each obj As Object In ar a.Add(obj) Next Return a End Sub 'Copied from log, generated by: GenerateCreateType Public Sub MyTypeFromMap(mp As Map) As MyType Dim t1 As MyType t1.Initialize If mp.ContainsKey("Name") Then t1.Name = mp.Get("Name") If mp.ContainsKey("City") Then t1.City = mp.Get("City") If mp.ContainsKey("Country") Then t1.Country = mp.Get("Country") If mp.ContainsKey("Amount") Then t1.Amount = mp.Get("Amount") If mp.ContainsKey("Grade") Then t1.Grade = mp.Get("Grade") If mp.ContainsKey("Phones") Then t1.Phones = mp.Get("Phones") If mp.ContainsKey("TestMap") Then t1.TestMap = mp.Get("TestMap") If mp.ContainsKey("TestArray") Then t1.TestArray = mp.Get("TestArray") Return t1 End Sub 'On Log 'Public Sub MyTypeFromMap(mp As Map) As MyType ' Dim t1 As MyType ' t1.Initialize ' If mp.ContainsKey("Name") Then t1.Name = mp.Get("Name") ' If mp.ContainsKey("City") Then t1.City = mp.Get("City") ' If mp.ContainsKey("Country") Then t1.Country = mp.Get("Country") ' If mp.ContainsKey("Amount") Then t1.Amount = mp.Get("Amount") ' If mp.ContainsKey("Grade") Then t1.Grade = mp.Get("Grade") ' If mp.ContainsKey("Phones") Then t1.Phones = mp.Get("Phones") ' If mp.ContainsKey("TestMap") Then t1.TestMap = mp.Get("TestMap") ' If mp.ContainsKey("TestArray") Then t1.TestArray = mp.Get("TestArray") ' Return t1 'End Sub