Lightweight and easy to use kotlinx.serialization plugin for TOML serialization and deserialization.
If you find any problem along usage, please raise an issue. 😉
Gradle Kotlin (build.gradle.kts)
repositories {
mavenCentral()
}
dependencies {
implementation("net.peanuuutz.tomlkt:tomlkt:0.3.3")
}
Gradle Groovy (build.gradle)
repositories {
mavenCentral()
}
dependencies {
implementation "net.peanuuutz.tomlkt:tomlkt:0.3.3"
}
Maven (.pom)
<dependency>
<groupId>net.peanuuutz.tomlkt</groupId>
<artifactId>tomlkt-jvm</artifactId>
<version>0.3.3</version>
</dependency>
Note: If your project is Kotlin Multiplatform, you can simply add this into commonMain dependencies.
Write some config:
name = "Peanuuutz"
[account]
username = "Peanuuutz"
password = "123456"
Write some code:
@Serializable
data class User(
val name: String,
val account: Account?
)
@Serializable
data class Account(
val username: String,
val password: String
)
fun main() {
// Here we use JVM.
val tomlString = Paths.get("...").readText()
// Either is OK, but to explicitly pass a serializer is faster.
val user = Toml.decodeFromString(User.serializer(), tomlString)
val user = Toml.decodeFromString<User>(tomlString)
// That's it!
// By the way if you need some configuration.
val toml = Toml {
ignoreUnknownKeys = true
}
// Use toml to apply the change.
// Serialization.
val anotherUser = User("Anonymous", null)
// Again, better to explicitly pass a serializer.
val config = Toml.encodeToString(User.serializer(), anotherUser)
Paths.get("...").writeText(config)
// Done.
}
TOML format | Serialization | Deserialization |
---|---|---|
Comment | ✔️ | ✔️ |
Key | ✔️ | ✔️ |
String | ✔️ | ✔️ |
Integer | ✔️ | ✔️ |
Float | ✔️ | ✔️ |
Boolean | ✔️ | ✔️ |
Date Time | ✔️ | ✔️ |
Array | ✔️ | ✔️ |
Table | ✔️ | ✔️❔ |
Inline Table | ✔️ | ✔️ |
Array of Tables | ✔️ | ✔️ |
Implemented as an annotation @TomlComment
on properties:
class IntData(
@TomlComment("""
An integer,
but is decoded into Long originally
""")
val int: Int
)
IntData(10086)
The code above will be encoded into:
# An integer,
# but is decoded into Long originally
int = 10086
Basic strings are encoded as "<content>"
. For multilines and literals, put an annotation as
below:
class MultilineStringData(
@TomlMultilineString
val multilineString: String
)
MultilineStringData("""
Do, a deer, a female deer.
Re, a drop of golden sun.
""".trimIndent())
class LiteralStringData(
@TomlLiteralString
val literalString: String
)
LiteralStringData("C:\\Users\\<User>\\.m2\\repositories")
The code above will be encoded into:
multilineString = """
Do, a deer, a female deer.
Re, a drop of golden sun."""
literalString = 'C:\Users\<User>\.m2\repositories'
You can use both annotations to get multiline literal string.
TOML supports several date time formats, so does tomlkt. tomlkt declares TomlLocalDateTime
,
TomlOffsetDateTime
, TomlLocalDate
, TomlLocalTime
as expect types with builtin support for
serialization (@Serializable
).
The mapping of these expect types are as follows:
tomlkt | java.time | kotlinx.datetime |
---|---|---|
TomlLocalDateTime | LocalDateTime | LocalDateTime |
TomlOffsetDateTime | OffsetDateTime | Instant |
TomlLocalDate | LocalDate | LocalDate |
TomlLocalTime | LocalTime | LocalTime |
TomlLiteral is the default intermediate representation of a date time. For conversion,
simply use TomlLiteral(TomlLocalDateTime)
to create a TomlLiteral
from a TomlLocalDateTime
(true for other types), and TomlLiteral.toLocalDateTime()
for the other way.
If you'd like to provide a custom serializer, use NativeLocalDateTime
and the like as raw types.
❔: There's an internal issue. When you define super-table before the sub-table:
[x]
[x.y]
It will be successfully parsed, but if you define after that:
[x.y]
[x]
It will throw net.peanuuutz.tomlkt.internal.ConflictEntryException
. Due to the reading process
of TomlFileParser, each time a table head is parsed, the path will be immediately put into
the whole tree, and meanwhile be checked if is already defined.
Better to keep super-table first!
The working process of tomlkt:
- Serialization: Model / TomlElement → (TomlFileEncoder) → File(String); Model → (TomlElementEncoder) → TomlElement.
- Deserialization: File(String) → (TomlFileParser) → TomlElement → (TomlElementDecoder) → Model.
As you see, if you already have a TOML file, you can have no model class, but still gain access to every entry with the help of TomlElement.
Note: Due to no context of values in TomlTable(see TomlElement.kt), all of those are encoded as inline(meaning you can't get the same serialized structure between model class and TomlTable).
For other information, view API docs.