-
Notifications
You must be signed in to change notification settings - Fork 11
Kotlin Examples
Falkreon edited this page Jan 17, 2019
·
2 revisions
build.gradle.kts
repositories {
mavenCentral()
}
dependencies {
implementation(group = "blue.endless", name = "jankson", version = Versions.jankson)
}
Versions.kt
// this file goes in buildSrc/src/main/kotlin
object Versions {
const val kotlin = "1.3.11"
const val jankson = "1.1.0"
// other versions here
}
JanksonSample.kt
import blue.endless.jankson.Comment
import blue.endless.jankson.Jankson
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
val configDirectory = File("run")
.resolve("config")
.apply {
mkdirs()
}
inline fun <reified T> loadConfig(): T {
val jankson = Jankson.builder()
//.registerTypeAdapter(...) //You can register adapters here to customize deserialization
//.registerSerializer(...) //Likewise, you can customize serializer behavior
.build() //In most cases, the default Jankson is all you need.
//Any file, String, or InputStream will do. This is just a Fabric example.
val configFile = configDirectory.resolve("mymod.json")
val configJson = jankson.load(configFile) //Takes the file and turns it into an object tree
//Takes a String or an object tree and deserializes it into a plain-java-object
val configObject = jankson.fromJson(configJson, T::class.java)
return configObject
}
/* Saving is more of the same. We just bake the config down to a String and write it out. */
inline fun <reified T> saveConfig(config: T = (T::class.java::newInstance)()) {
val configFile = configDirectory.resolve("mymod.json")
val jankson = Jankson.builder().build()
val result = jankson
.toJson(config) //The first call makes a JsonObject
.toJson(true, true, 0) //The second turns the JsonObject into a String -
//in this case, preserving comments and inserting newlines
try {
if (!configFile.exists()) configFile.createNewFile()
val out = FileOutputStream(configFile, false)
out.write(result.toByteArray())
out.flush()
out.close()
} catch (ex: IOException) {
ex.printStackTrace()
}
}
/* The main thing you need to have, to benefit from auto-deserialization, is a no-arg constructor.
* in this case, all fields have default values so a no-arg constructor overload is generated
*/
data class ConfigObject(
/* Comment annotations populate serialized keys with json5 comments */
@Comment("why orbs?")
var maxOrbs: Int = 10,
/* Collection and map types are properly captured in both directions. Beware of nested collections!
* We're still working on making List<List<String>> deserialize properly. If you need nested generics
* like this, skip ahead to the Jankson+GSON setup!
*/
private val someStrings: List<String> = listOf("abc", "cde"),
/* While it's always best to have the object initialized in the constructor or initializer, as long
* as a full, concrete type is declared, Jankson can create the instance and fill it in.
*/
protected var uninitializedMap: Map<String, String>? = null,
protected var initializedMap: Map<String, String> = mapOf("a" to "b", "c" to "d"),
// at runtime this will be java.lang.Integer[]
val integerArray: Array<Int> = arrayOf(1, 2, 4),
// at runtime this will be int[]
val intArray: IntArray = arrayOf(1, 2, 3).toIntArray(),
val nested: NestedConfig = NestedConfig()
) {
/*
nested configurations with inner classes are also possible
*/
data class NestedConfig(
val nestedData: Set<Short> = setOf(1, 2, 3)
)
}
fun main() {
saveConfig<ConfigObject>()
val config = loadConfig<ConfigObject>()
println("config object >>> $config")
}