kotlinx-uuid icon indicating copy to clipboard operation
kotlinx-uuid copied to clipboard

kotlinx-uuid is a multiplatform (MPP) Kotlin library introducing support for UUID.

GitHub license

kotlinx-uuid

This library is experimental, and it's future support is not guaranteed.
Table of Contents
  • Including
  • Usage: from string, generating, hashing
  • Serialization
  • Using with ktor
  • Migrating from java.util.UUID
  • Using with Exposed
  • Using with Gson
  • Using with Jackson

kotlinx-uuid is a multiplatform (MPP) Kotlin library introducing support for UUID.

The main class UUID is serializable out of the box, so the library depends on kotlinx.serialization. If you don't need serialization, you don't need to apply the plugin.

Supported platforms are:

  • JVM (Java 6+)
  • JavaScript (including the new IR backend)
  • Native:
    • MacOS X64, iOS ARM64 (untested)
    • Linux X64, ARM64 (untested)

*untested means that on that platform we didn't run any tests, just compiled.

Including

repositories {
    maven("https://maven.pkg.github.com/cy6ergn0m/kotlinx-uuid")
}

val commonMain by getting {
    dependencies {
        implementation("org.jetbrains.kotlinx.experimental:kotlinx-uuid-core:0.1.0")
    }
}

In a regular (non-MPP) project you don't need the line with "commonMain", only the dependencies block.

Usage

Creating from a UUID string

val uuid = UUID("1b3e4567-e99b-13d3-a476-446657420000")
val guid = UUID("{1b3e4567-e99b-13d3-a476-446657420000}")

Generating UUID4 using random

// using the default insecure kotlin.Random
val uuid = UUID.generateUUID()

// use secure random (just like java.util.UUID does)
val secure = UUID.generateUUID(SecureRandom().asKotlinRandom())

Generating UUID5 using hash

kotlinx-uuid provides the ability to generate uuids by hashing names (Only SHA-1 is supported at the moment).

val appNamespace = UUID("my-app-uuid")
val agentId = UUID.generateUUID(appNamespace, "agentId")

The other alternative is to generate UUID by hashing bytes (similar to java.util.UUID.nameUUIDFromBytes).

val uuid = UUID.generateUUID(bytes)

Note that unlike java.util.UUID, kotlinx's generateUUID doesn't support MD5, so the blind migration from Java to kotlinx-uuid may lead to changing UUIDs.

Serializing (kotlinx.serialization)

There are two serializers for UUID: the default one and the binary.

The default serializer does always serialize UUIDs as string primitives.

Json.encodeToString(uuid) == "\"1b3e4567-e99b-13d3-a476-446657420000\""

The additional serializer is useful for binary formats. Because they are not human-readable, and it's possible to reduce size.

val bytes = Protobuf.encodeToByteArray(BinarySerializer, uuid)

Using with ktor

Include ktor-server-uuid artifact:

repositories {
    maven("https://maven.pkg.github.com/cy6ergn0m/kotlinx-uuid")
}

val jvmMain by getting {
    dependencies {
        implementation("org.jetbrains.kotlinx.experimental:ktor-server-uuid:0.1.0")
    }
}

Install converter:

install(DataConversion) {
    uuid()
}

Unfortunately, ktor doesn't provide (KTOR-1309) any way to plug converters automatically, so you need to configure it manually. Also, in some cases, like delegating to call parameters, it will not work and there is no workaround at the moment.

At the moment, DataConversion is going through the deprecation cycle due to server MPP migration. So there are two ConversionService interfaces. Using uuid() function is recommended without referreing to particular types.

Migrating from java.util.UUID

Apply the following steps:

  1. Remove all imports of import java.util.UUID
  2. Add imports for UUID
import kotlinx.uuid.UUID
import kotlinx.uuid.*
  1. Follow deprecations and apply all suggested replacements.

For example:

import java.util.UUID

fun f(id: String): UUID = UUID.fromString(id)

Becomes

import kotlinx.uuid.UUID

fun f(id: String) = UUID(id)

Note that unlike java.util.UUID.nameUUIDFromBytes, kotlinx's generateUUID doesn't support MD5, so the blind migration from Java to kotlinx-uuid may lead to changing UUIDs. This is why it is marked as error, so you need to think first, if you can simply replace it or not.

Using with Exposed

Exposed is an ORM framework for Kotlin. It has support for java.util.UUID, but to get kotlinx-uuid supported you need to include the corresponding dependency and use DSL functions:

repositories {
    maven("https://maven.pkg.github.com/cy6ergn0m/kotlinx-uuidd")
}

dependencies {
    implementation("org.jetbrains.kotlinx.experimental:exposed-uuid:0.1.0")
}

When declaring a table having UUID as Primary Key:

// SQL DSL
object MyTable : KotlinxUUIDTable() {
    // there is "id" property with the kotlinx-uuid type
}

// DAO API
class MyTableEntity(id: EntityID<UUID>): KotlinxUUIDEntity(id) {
    companion object: KotlinxUUIDEntityClass<MyTableEntity>(MyTable)
    
} 

To declare a regular column, use kotlinxUUID function:

object MyTable : Table() {
    val something = kotlinxUUID("SOME_COLUMN")
}

Unfortunately, there is a function called uuid in the base class, inside of the exposed core, this is why we can't overwrite/override it so it may lead to confusion. The function uuid only works with java.util.UUID:

object MyTable : Table() {
    val column1 = kotlinxUUID("C1") // kotlinx.uuid.UUID
    val column2 = uuid("C2") // java.util.UUID
}

Using with Gson

To use [UUID] with Gson you need to register the serializer:

repositories {
    maven("https://maven.pkg.github.com/cy6ergn0m/kotlinx-uuid")
}

dependencies {
    implementation("org.jetbrains.kotlinx.experimental:gson-uuid:0.1.0")
}
val gson = GsonBuilder().registerUUID().create()

After that [UUID] will be serialized to JSON string primitives.

Using with Jackson

To use [UUID] with Jackson you need to register the module:

repositories {
    maven("https://maven.pkg.github.com/cy6ergn0m/kotlinx-uuid")
}

dependencies {
    implementation("org.jetbrains.kotlinx.experimental:jackson-module-uuid:0.1.0")
}
val jackson = ObjectMapper().uuid()

val json = jackson.writeValueAsString(
    UUID.generateUUID()
)

After that [UUID] will be serialized to JSON string primitives.

Having jackson-module-kotlin is recommended but not required.