3

I have a Kotlin object that I need converted into a byte array (byte[]). I understand how to convert a String and a series of other kinds of variables into byte[], but I can't find anything on doing this with an object.

Here is what I've tried:

override fun activateQuestion(instructorUserName: String, host: String, port: Int, questionToActivate: MultipleChoiceQuestion) {
        val socket = DatagramSocket()

        //This is the problem -- `.toByteArray(...)` only works for Strings
        val questionToActivateAsByteArray = questionToActivate.toByteArray(Charsets.UTF_8)

        //send byte[] data 
        val packet = DatagramPacket(questionToActivateAsByteArray, questionToActivateAsByteArray.size, InetAddress.getByName(host), port)
        socket.send(packet)
    }
Vismark Juarez
  • 613
  • 4
  • 14
  • 21
  • 1
    https://stackoverflow.com/questions/4252294/sending-objects-across-network-using-udp-in-java – IR42 Apr 05 '20 at 17:34
  • I usually opt to use json when sending objects over the wire. It allows you to decode them in any language. I would use a Jackson `ObjectMapper` and convert your object to a string before sending it as bytes. – flakes Apr 05 '20 at 18:00
  • Have you found a solution? I am wondering the same. – IgorGanapolsky May 29 '20 at 15:54

3 Answers3

3

You can convert to bytearray in the java style. Something like this: Java Serializable Object to Byte Array

edit: to make it easier, its utility functions will look like this:

import java.io.*

@Suppress("UNCHECKED_CAST")
fun <T : Serializable> fromByteArray(byteArray: ByteArray): T {
    val byteArrayInputStream = ByteArrayInputStream(byteArray)
    val objectInput: ObjectInput
    objectInput = ObjectInputStream(byteArrayInputStream)
    val result = objectInput.readObject() as T
    objectInput.close()
    byteArrayInputStream.close()
    return result
}

fun Serializable.toByteArray(): ByteArray {
    val byteArrayOutputStream = ByteArrayOutputStream()
    val objectOutputStream: ObjectOutputStream
    objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
    objectOutputStream.writeObject(this)
    objectOutputStream.flush()
    val result = byteArrayOutputStream.toByteArray()
    byteArrayOutputStream.close()
    objectOutputStream.close()
    return result
}

to use them is just to do something like:

val yourSerializableObject = YourSerializableObject(...)
val objectInByteArrayFormat = yourSerializableObject.toByteArray()
val convertedObject = fromByteArray<YourSerializableObject>(objectInByteArrayFormat)

Don't forget that your object and all its attributes must be serializable

3

Easiest way I've found with Kotlinx's serialization:

Mark your data class with @Serializable (if this isn't working for you, add the necessary plugins and dependencies to your build.gradle files).

@Serializable
data class User(val name: String, val age: Int)

Then when you create an instance of it, you convert it into a Json string into a byte array it via Json.encodeToString(yourInstance).toByteArray().

Example:

val user = User(Mohammed, 25)
val userAsByteArray = Json.encodeToString(user).toByteArray()
M.Ed
  • 969
  • 10
  • 12
2

The following is an object serializable class which is helpful to convert the object to bytes array and vice versa in Kotlin.

public class ObjectSerializer {
    companion object {
        public fun serialize(obj: Any?) : String {
            if (obj == null) {
                return ""
            }

            var baos = ByteArrayOutputStream()
            var oos = ObjectOutputStream(baos)
            oos.writeObject(obj)
            oos.close()

            return encodeBytes(baos.toByteArray())
        }

        public fun deserialize(str: String?) : Any? {
            if (str == null || str.length() == 0) {
                return null
            }

            var bais = ByteArrayInputStream(decodeBytes(str))
            var ois = ObjectInputStream(bais)

            return ois.readObject()
        }

        private fun encodeBytes(bytes: ByteArray) : String {
            var buffer = StringBuffer()

            for (byte in bytes) {
                buffer.append(((byte.toInt() shr 4) and 0xF plus 'a').toChar())
                buffer.append(((byte.toInt()) and 0xF plus 'a').toChar())
            }

            return buffer.toString()
        }

        private fun decodeBytes(str: String) : ByteArray {
            var bytes = ByteArray(str.length() / 2)

            for (i in 0..(str.length() - 1)) {
                var c = str.charAt(i)
                bytes.set(i / 2, ((c minus 'a').toInt() shl 4).toByte())

                c = str.charAt(i + 1)
                bytes.set(i / 2, (bytes.get(i / 2) + (c minus 'a')).toByte())
            }

            return bytes
        }
    }
}
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81
  • Could you please also include the package import part? Some dependencies didn't work when I copy your code to my local IDE. – Lysander Sep 12 '22 at 01:16