B4A Library [B4X] .Net Framework implementation of B4XSerializator

B4XSerializator is included in the internal RandomAccessFile library. The attached dll is for .Net Framework applications.
B4XSerializator is a great tool that makes it simple to share data between B4A, B4i and B4J. It takes care of converting objects, including complex objects, to bytes and vice versa. (It also has a smaller brother named B4RSerializator that is supported by B4A, B4i, B4J and B4R but is less powerful.)

Example: https://www.b4x.com/android/forum/threads/network-asyncstreams-b4xserializator.72149/#content

The attached .Net dll is a .Net implementation of B4XSerializator. You can use it if you need to communicate with a .Net application or server.

Using it is simple. Create a B4XSerializator object and call ConvertBytesToObject or ConvertObjectToBytes.
Custom B4X types will be converted to a class named B4XType. B4XType holds the class name and a dictionary (map) with the fields names and values.
You can also create B4XType instances yourself.

Tips & Notes

- The following types are supported: primitives, strings, List<Object>, Dictionary<Object, Object>, arrays of objects, arrays of bytes and B4XType objects. Including combinations of these types (lists of maps with custom types for example).
- It depends on SharpZipLib. It is included in the zip file. License (allows commercial usage): http://icsharpcode.github.io/SharpZipLib/
- The c# code is included.
 

Attachments

  • .Net_B4XSerializator.zip
    86.3 KB · Views: 1,440
Last edited:

mmieher

Active Member
Licensed User
Longtime User
I am trying to convert Erel's .Net_B4XSerializator from C# to VB.NET.
I know very little about C# and am having a problem with syntax of B4XType
B4X:
Private Function readType(o As Object)
    Dim cls As String = readObject(o)
    Dim data As VariantType = readMap(o)
    Return New B4XType(cls, data)    '<===== "Too many arguments to Public Sub New()"  cls is underlined
    End Function
     
Public Class B4XType
    Public ClassName As String
    Public Fields As Dictionary(Of Object, Object)
 
    Public Sub B4XType(ClassName As String, data As Dictionary(Of Object, Object))
        Dim i As Integer = ClassName.LastIndexOf("$")
            If i > -1 Then
                ClassName = ClassName.Substring(i + 2)
            ElseIf ClassName.StartsWith("_") Then
                ClassName = ClassName.Substring(1)
            Else
                ClassName = ClassName.ToLower(New CultureInfo("en-US", False))
                Me.ClassName = ClassName
                Me.Fields = data
            End If
        End Sub
    End Class
Does anyone see what is wrong here?
 

LucaMs

Expert
Licensed User
Longtime User
http://converter.telerik.com/

B4X:
Imports System
Imports System.Collections.Generic
Imports System.Globalization
Imports System.IO
Imports System.Linq
Imports System.Text
Imports ICSharpCode.SharpZipLib.Zip.Compression.Streams

Namespace WpfApplication1

    Public Class B4XSerializator

        Private Const T_NULL As Byte = 0, T_STRING As Byte = 1, T_SHORT As Byte = 2, T_INT As Byte = 3, T_LONG As Byte = 4, T_FLOAT As Byte = 5, T_DOUBLE As Byte = 6, T_BOOLEAN As Byte = 7, T_BYTE As Byte = 10, T_CHAR As Byte = 14, T_MAP As Byte = 20, T_LIST As Byte = 21, T_NSARRAY As Byte = 22, T_NSDATA As Byte = 23, T_TYPE As Byte = 24

        Private br As BinaryReader

        Private bw As BinaryWriter

        Private ReadOnly utf8 As UTF8Encoding

        Public Sub New()
            utf8 = New UTF8Encoding(False)
        End Sub

        Public Function ConvertBytesToObject(ByVal Bytes As Byte()) As Object
            Using inf As InflaterInputStream = New InflaterInputStream(New MemoryStream(Bytes))
                br = New BinaryReader(inf)
                Dim ret As Object = readObject()
                Return ret
            End Using
        End Function

        Public Function ConvertObjectToBytes(ByVal Object As Object) As Byte()
            Dim ms As MemoryStream = New MemoryStream()
            Using def As DeflaterOutputStream = New DeflaterOutputStream(ms)
                bw = New BinaryWriter(def)
                writeObject(Object)
            End Using

            Return ms.ToArray()
        End Function

        Private Sub writeObject(ByVal o As Object)
            If o Is Nothing Then
                writeByte(T_NULL)
            ElseIf TypeOf o Is Integer Then
                writeByte(T_INT)
                writeInt(CInt(o))
            ElseIf TypeOf o Is Double Then
                writeByte(T_DOUBLE)
                bw.Write(CDbl(o))
            ElseIf TypeOf o Is Single Then
                writeByte(T_FLOAT)
                bw.Write(CSng(o))
            ElseIf TypeOf o Is Long Then
                writeByte(T_LONG)
                bw.Write(CLng(o))
            ElseIf TypeOf o Is Byte Then
                writeByte(T_BYTE)
                bw.Write(CByte(o))
            ElseIf TypeOf o Is Short Then
                writeByte(T_SHORT)
                bw.Write(CShort(o))
            ElseIf TypeOf o Is Char Then
                writeByte(T_CHAR)
                bw.Write(CShort(CChar(o)))
            ElseIf TypeOf o Is Boolean Then
                writeByte(T_BOOLEAN)
                writeByte(CByte((If(CBool(o), 1, 0))))
            ElseIf TypeOf o Is String Then
                Dim temp As Byte() = utf8.GetBytes(CStr(o))
                writeByte(T_STRING)
                writeInt(temp.Length)
                bw.Write(temp, 0, temp.Length)
            ElseIf TypeOf o Is List(Of Object) Then
                writeByte(T_LIST)
                writeList(CType(o, List(Of Object)))
            ElseIf TypeOf o Is Dictionary(Of Object, Object) Then
                writeByte(T_MAP)
                writeMap(CType(o, Dictionary(Of Object, Object)))
            ElseIf o.[GetType]().IsArray Then
                If TypeOf o Is Byte() Then
                    writeByte(T_NSDATA)
                    Dim b As Byte() = CType(o, Byte())
                    writeInt(b.Length)
                    bw.Write(b, 0, b.Length)
                ElseIf TypeOf o Is Object() Then
                    writeByte(T_NSARRAY)
                    writeList(New List(Of Object)(CType(o, Object())))
                Else
                    Throw New Exception("Only arrays of bytes or objects are supported.")
                End If
            ElseIf TypeOf o Is B4XType Then
                writeByte(T_TYPE)
                writeType(CType(o, B4XType))
            Else
                Throw New Exception("Type not supported: " & o.[GetType]())
            End If
        End Sub

        Private Sub writeMap(ByVal m As Dictionary(Of Object, Object))
            writeInt(m.Count)
            For Each kvp As KeyValuePair(Of Object, Object) In m
                writeObject(kvp.Key)
                writeObject(kvp.Value)
            Next
        End Sub

        Private Sub writeList(ByVal list As List(Of Object))
            writeInt(list.Count)
            For Each o As Object In list
                writeObject(o)
            Next
        End Sub

        Private Function readObject() As Object
            Dim t As Byte = br.ReadByte()
            Dim len As Integer
            Dim b As Byte()
            Select Case t
                Case T_NULL
                    Return Nothing
                Case T_INT
                    Return readInt()
                Case T_SHORT
                    Return readShort()
                Case T_LONG
                    Return br.ReadInt64()
                Case T_FLOAT
                    Return br.ReadSingle()
                Case T_DOUBLE
                    Return br.ReadDouble()
                Case T_BOOLEAN
                    Return br.ReadByte() = 1
                Case T_BYTE
                    Return br.ReadByte()
                Case T_STRING
                    len = readInt()
                    b = br.ReadBytes(len)
                    Return utf8.GetString(b)
                Case T_CHAR
                    Return CChar(readShort())
                Case T_LIST
                    Return readList()
                Case T_MAP
                    Return readMap()
                Case T_NSDATA
                    len = readInt()
                    Return br.ReadBytes(len)
                Case T_NSARRAY
                    Dim list As List(Of Object) = readList()
                    Return list.ToArray()
                Case T_TYPE
                    Return readType()
                Case Else
                    Throw New Exception("Unsupported type: " & t)
            End Select
        End Function

        Private Sub writeByte(ByVal b As Byte)
            bw.Write(b)
        End Sub

        Private Sub writeInt(ByVal i As Integer)
            bw.Write(i)
        End Sub

        Private Function readList() As List(Of Object)
            Dim len As Integer = readInt()
            Dim arr As List(Of Object) = New List(Of Object)(len)
            For i As Integer = 0 To len - 1
                arr.Add(readObject())
            Next

            Return arr
        End Function

        Private Function readMap() As Dictionary(Of Object, Object)
            Dim len As Integer = readInt()
            Dim mm As Dictionary(Of Object, Object) = New Dictionary(Of Object, Object)()
            For i As Integer = 0 To len - 1
                mm(readObject()) = readObject()
            Next

            Return mm
        End Function

        Private Function readInt() As Integer
            Return br.ReadInt32()
        End Function

        Private Function readShort() As Short
            Return br.ReadInt16()
        End Function

        Private Function readType() As Object
            Dim cls As String = CStr(readObject())
            Dim data = readMap()
            Return New B4XType(cls, data)
        End Function

        Private Sub writeType(ByVal t As B4XType)
            writeObject("_" & t.ClassName)
            writeMap(t.Fields)
        End Sub
    End Class

    Public Class B4XType

        Public ReadOnly ClassName As String

        Public ReadOnly Fields As Dictionary(Of Object, Object)

        Public Sub New(ByVal className As String, ByVal data As Dictionary(Of Object, Object))
            Dim i As Integer = className.LastIndexOf("$")
            If i > -1 Then
                className = className.Substring(i + 2)
            ElseIf className.StartsWith("_") Then
                className = className.Substring(1)
            Else
                className = className.ToLower(New CultureInfo("en-US", False))
            End If

            Me.ClassName = className
            Me.Fields = data
        End Sub
    End Class
End Namespace

'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by Refactoring Essentials.
'Twitter: @telerik
'Facebook: facebook.com/telerik
'=======================================================
 

mmieher

Active Member
Licensed User
Longtime User
Wow! What a fantastic tool! Knowing about this years ago would have saved me thousands of hours. Thank you!
 

LucaMs

Expert
Licensed User
Longtime User
I saw the comment lines on the bottom of the source code converted:
B4X:
'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by Refactoring Essentials.
'Twitter: @telerik
'Facebook: facebook.com/telerik
'=======================================================

"powered by Refactoring Essentials"? Well, Luca AKA Mario :D, search for it, to know what is it ;)

Found:
http://vsrefactoringessentials.com/

(I think I will install it soon).
 

mmieher

Active Member
Licensed User
Longtime User
"Using it is simple. Create a B4XSerializator object and call ConvertBytesToObject or ConvertObjectToBytes.
Custom B4X types will be converted to a class named B4XType. B4XType holds the class name and a dictionary (map) with the fields names and values."

Ok, I need a little more help here. What exactly is the VB.NET syntax to do the "simple" steps above? All my attempts have failed.
 

Toky Olivier

Active Member
Licensed User
Longtime User
I ported also @Erel's source of B4XSerializator to Php. I'll post it here when I finish. Now it's working but only with basic types. I'll add Lists, Maps and custom Types.
 
Last edited:

alimanam3386

Active Member
Licensed User
Longtime User
I know this lib is for .net but how can we have like this lib in javascrip ? I put data ( it is a byte array ) in a map and after serialize it by B4XSerializator
B4X:
' Private ser As B4XSerializator
Sub b4astreamer_RecordBuffer (Data() As Byte)
    Dim m As Map = CreateMap("data" : Data , "room" : "room1")
    EmitToServer("broadcast" , ser.ConvertObjectToBytes(m))
End Sub

in server side how can I deserliaze this object ( map )?
 
Top