Skip to content

Commit 9344541

Browse files
authored
KTLN-526 - Convert a Data Class to ByteBuffer in Kotlin (#1090)
* feat: data class to and from byte buffer * fix: properties in xml, user class
1 parent 47998b4 commit 9344541

File tree

7 files changed

+228
-0
lines changed

7 files changed

+228
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
### Relevant Articles
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5+
http://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
<artifactId>core-kotlin-11</artifactId>
8+
<name>core-kotlin-11</name>
9+
<packaging>jar</packaging>
10+
11+
<parent>
12+
<groupId>com.baeldung</groupId>
13+
<artifactId>core-kotlin-modules</artifactId>
14+
<version>1.0.0-SNAPSHOT</version>
15+
</parent>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>org.jetbrains.kotlin</groupId>
20+
<artifactId>kotlin-maven-serialization</artifactId>
21+
<version>${kotlin.version}</version>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.jetbrains.kotlinx</groupId>
25+
<artifactId>kotlinx-serialization-json</artifactId>
26+
<version>${kotlinx.serialization.version}</version>
27+
</dependency>
28+
<dependency>
29+
<groupId>com.esotericsoftware.kryo</groupId>
30+
<artifactId>kryo</artifactId>
31+
<version>${kryo.version}</version>
32+
</dependency>
33+
</dependencies>
34+
35+
<build>
36+
<sourceDirectory>src/main/kotlin</sourceDirectory>
37+
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
38+
<plugins>
39+
<plugin>
40+
<groupId>org.jetbrains.kotlin</groupId>
41+
<artifactId>kotlin-maven-plugin</artifactId>
42+
<version>${kotlin.version}</version>
43+
<executions>
44+
<execution>
45+
<id>compile</id>
46+
<phase>compile</phase>
47+
<goals>
48+
<goal>compile</goal>
49+
</goals>
50+
</execution>
51+
</executions>
52+
<configuration>
53+
<compilerPlugins>
54+
<plugin>kotlinx-serialization</plugin>
55+
</compilerPlugins>
56+
</configuration>
57+
</plugin>
58+
</plugins>
59+
</build>
60+
61+
<properties>
62+
<kotlinx.serialization.version>1.4.1</kotlinx.serialization.version>
63+
<kryo.version>2.24.0</kryo.version>
64+
</properties>
65+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.baeldung.dataclasstobytebuffer
2+
3+
import com.esotericsoftware.kryo.Kryo
4+
import com.esotericsoftware.kryo.io.Input
5+
import com.esotericsoftware.kryo.io.Output
6+
import java.io.ByteArrayInputStream
7+
import java.io.ByteArrayOutputStream
8+
import java.nio.ByteBuffer
9+
10+
data class User(val id: Int = 0, val name: String = "", val age: Int = 0)
11+
12+
fun User.manualToByteBuffer(): ByteBuffer {
13+
val nameBytes = this.name.toByteArray(Charsets.UTF_8)
14+
val buffer = ByteBuffer.allocate(Int.SIZE_BYTES + nameBytes.size + Int.SIZE_BYTES)
15+
16+
buffer.putInt(this.id)
17+
buffer.put(nameBytes)
18+
buffer.putInt(this.age)
19+
20+
buffer.flip() // Prepare the buffer for reading
21+
22+
return buffer
23+
}
24+
25+
fun ByteBuffer.manualToUser(): User {
26+
val id = this.int
27+
val nameBytes = ByteArray(this.remaining() - Int.SIZE_BYTES)
28+
this.get(nameBytes)
29+
val name = String(nameBytes, Charsets.UTF_8)
30+
val age = this.int
31+
32+
return User(id, name, age)
33+
}
34+
35+
// Using Kryo
36+
37+
fun User.toByteBufferWithKryo(kryo: Kryo): ByteBuffer {
38+
val byteArrayOutputStream = ByteArrayOutputStream()
39+
val output = Output(byteArrayOutputStream)
40+
kryo.writeObject(output, this)
41+
output.close()
42+
43+
val byteArray = byteArrayOutputStream.toByteArray()
44+
return ByteBuffer.wrap(byteArray)
45+
}
46+
47+
fun ByteBuffer.toUserWithKryo(kryo: Kryo): User {
48+
val byteArray = ByteArray(this.remaining())
49+
this.get(byteArray)
50+
51+
val byteArrayInputStream = ByteArrayInputStream(byteArray)
52+
val input = Input(byteArrayInputStream)
53+
return kryo.readObject(input, User::class.java).also { input.close() }
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.baeldung.dataclasstobytebuffer
2+
3+
import java.io.*
4+
import java.nio.ByteBuffer
5+
6+
data class UserInputOutputStream(val id: Int, val name: String, val age: Int) : Serializable
7+
8+
fun UserInputOutputStream.outputStreamByteBuffer(): ByteBuffer {
9+
val byteArrayOutputStream = ByteArrayOutputStream()
10+
val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
11+
12+
objectOutputStream.writeObject(this)
13+
objectOutputStream.flush()
14+
15+
val byteArray = byteArrayOutputStream.toByteArray()
16+
return ByteBuffer.wrap(byteArray)
17+
}
18+
19+
fun ByteBuffer.inputStreamToUser(): UserInputOutputStream {
20+
val byteArray = ByteArray(this.remaining())
21+
this.get(byteArray)
22+
23+
val byteArrayInputStream = ByteArrayInputStream(byteArray)
24+
val objectInputStream = ObjectInputStream(byteArrayInputStream)
25+
26+
return objectInputStream.readObject() as UserInputOutputStream
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.baeldung.dataclasstobytebuffer
2+
3+
import kotlinx.serialization.Serializable
4+
import kotlinx.serialization.decodeFromString
5+
import kotlinx.serialization.encodeToString
6+
import kotlinx.serialization.json.Json
7+
import java.nio.ByteBuffer
8+
import java.nio.charset.StandardCharsets
9+
10+
@Serializable
11+
data class UserSerialization(val id: Int, val name: String, val age: Int)
12+
13+
fun UserSerialization.userToJson(): ByteBuffer {
14+
val jsonString = Json.encodeToString(this)
15+
val byteArray = jsonString.toByteArray()
16+
return ByteBuffer.wrap(byteArray)
17+
}
18+
19+
fun ByteBuffer.jsonToUser(): UserSerialization {
20+
val byteArray = ByteArray(this.remaining())
21+
this.get(byteArray)
22+
val jsonString = String(byteArray, StandardCharsets.UTF_8)
23+
return Json.decodeFromString(jsonString)
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.baeldung.dataclasstobytebuffer
2+
3+
import com.esotericsoftware.kryo.Kryo
4+
import org.junit.Test
5+
import org.junit.jupiter.api.Assertions.assertEquals
6+
7+
class DataClassToByteBufferUnitTest {
8+
9+
private val kryo = Kryo().apply {
10+
register(User::class.java)
11+
}
12+
13+
@Test
14+
fun `Manual serialize and deserialize with fixed size`() {
15+
val user = User(id = 1, name = "Alice", age = 30)
16+
17+
val serializedUser = user.manualToByteBuffer()
18+
19+
val deserializedUser = serializedUser.manualToUser()
20+
21+
assertEquals(user, deserializedUser)
22+
}
23+
24+
@Test
25+
fun `Serialize and deserialize using byte array output and input stream`() {
26+
val user = UserInputOutputStream(id = 1, name = "Alice", age = 30)
27+
28+
val serializedUser = user.outputStreamByteBuffer()
29+
30+
val deserializedUser = serializedUser.inputStreamToUser()
31+
32+
assertEquals(user, deserializedUser)
33+
}
34+
35+
@Test
36+
fun `Serialize and deserialize using kotlin serialization library`() {
37+
val user = UserSerialization(id = 1, name = "Alice", age = 30)
38+
39+
val serializedUser = user.userToJson()
40+
41+
val deserializedUser = serializedUser.jsonToUser()
42+
43+
assertEquals(user, deserializedUser)
44+
}
45+
46+
@Test
47+
fun `Serialize and deserialize using Kryo library`() {
48+
val user = User(id = 1, name = "Alice", age = 30)
49+
50+
val serializedUser = user.toByteBufferWithKryo(kryo)
51+
52+
val deserializedUser = serializedUser.toUserWithKryo(kryo)
53+
54+
assertEquals(user, deserializedUser)
55+
}
56+
}

core-kotlin-modules/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<module>core-kotlin-8</module>
2626
<module>core-kotlin-9</module>
2727
<module>core-kotlin-10</module>
28+
<module>core-kotlin-11</module>
2829
<module>core-kotlin-advanced</module>
2930
<module>core-kotlin-advanced-2</module>
3031
<module>core-kotlin-advanced-3</module>

0 commit comments

Comments
 (0)