Protobuf Study With Kotlin

Source:


Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.

shell

➜ ls -lh jsonData.json employeeBinary 
-rw-r--r-- 1 user user  52B Aug 13 17:54 employeeBinary
-rw-r--r-- 1 user user 247B Aug 13 17:02 jsonData.json

kotlin

plugins {
	// https://mvnrepository.com/artifact/com.google.protobuf/protobuf-gradle-plugin
	runtimeOnly("com.google.protobuf:protobuf-gradle-plugin:0.9.4")
}

<->

dependencies {
    // https://mvnrepository.com/artifact/com.google.protobuf/protobuf-kotlin-lite
	implementation("com.google.protobuf:protobuf-kotlin-lite:3.24.0")
}

<->

protobuf {
    protoc {
	    // https://mvnrepository.com/artifact/com.google.protobuf/protoc
        artifact = "com.google.protobuf:protoc:3.24.0"
    }
    generateProtoTasks {
        all().forEach { task ->
            task.plugins {
                create("java") {
                    option("lite")
                }
            }
        }
    }
}

Caution: you should choose the new release version when you configure these dependencies, and These build.gradle.kts are in module.

text

syntax = "proto3";

option java_package = "$(package.name)";
option java_multiple_files = true;


message Employee {
  int32 id = 1;
  string name = 2;
  float salary = 3;
}

message Employees{
  repeated Employee employees = 1;
}

Caution: You may need to compile the code after completing the above operation.

Main Content for Proto

kotlin

fun main(): Unit {

    val hussein = Employee.newBuilder()
        .setId(1001)
        .setName("Hussein")
        .setSalary(1001F)
        .build()

    val ahmed = Employee.newBuilder()
        .setId(1002)
        .setName("Ahmed")
        .setSalary(9000F)
        .build()

    val rick = Employee.newBuilder()
        .setId(1003)
        .setName("Rick")
        .setSalary(5000F)
        .build()

    val employees = Employees.newBuilder()
        .addEmployees(hussein)
        .addEmployees(ahmed)
        .addEmployees(rick)
        .build()

    val byteArray = employees.toByteArray()

    println("binary $byteArray")

    File("employeeBinary").writeBytes(byteArray)

    println(Employees.parseFrom(byteArray))
}

and then, you will find a file “employeeBinary”, and it is located at the root of the project.

see it using the command line in Linux.


kotlin

plugins {
	// https://mvnrepository.com/artifact/org.jetbrains.kotlin.plugin.serialization/org.jetbrains.kotlin.plugin.serialization.gradle.plugin
	implementation("org.jetbrains.kotlin.plugin.serialization:1.9.0")
}

<->

dependencies {
	// https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-serialization-json-jvm
	runtimeOnly("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.5.1")
}

kotlin

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

Main Content for Json

kotlin

fun main(): Unit {
    val employees = mutableListOf<User>()

    val user1 = User("John Doe", 1000, 1001)
    val user2 = User("Ahmed", 9000, 1002)
    val user3 = User("Rick", 5000, 1003)
    employees.add(user1)
    employees.add(user2)
    employees.add(user3)

    val json = Json { prettyPrint = true }

    val jsonString: String = json.encodeToString(employees)
    println(jsonString)
    File("jsonData.json").writeText(jsonString)
}

and then, you will find a file “jsonData.json”, and it is located at the root of the project.

see it using the command line in Linux.


as mentioned earlier, the size of proto’s file is less than the size of json’s file.

let’s continuing studing.

thanks to these resources on the internet, and also thanks for reading.