Kotlin JSON stream serializer - Compile-time generated Kotlin Multiplatform JSON stream serialization
Kotlin JSON stream serializer is a KSP plugin, that allows you to annotate certain classes and have JSON serialization/deserialization functions generated for them at compile-time.
Sample: For a sample project go to kotlin-json-stream-serializer-sample.
plugins {
kotlin("jvm").version("2.1.20")
id("com.google.devtools.ksp") version("2.1.20-1.0.31")
}
repositories {
mavenCentral()
}
dependencies {
ksp("com.fab1an:kotlin-json-stream-serializer:2.0.4")
implementation("com.fab1an:kotlin-json-stream-serializer-annotations:2.0.1")
implementation("com.fab1an:kotlin-json-stream:1.2.3")
}
plugins {
kotlin("multiplatform").version("2.1.10")
id("com.google.devtools.ksp").version("2.1.10-1.0.30")
}
repositories {
mavenCentral()
}
kotlin {
macosX64()
jvm()
applyDefaultHierarchyTemplate()
sourceSets {
commonMain {
dependencies {
implementation("com.fab1an:kotlin-json-stream-serializer-annotations:2.0.0")
implementation("com.fab1an:kotlin-json-stream:1.2.3")
}
kotlin {
srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}
}
}
}
dependencies {
add("kspCommonMainMetadata", "com.fab1an:kotlin-json-stream-serializer:2.0.3")
}
tasks.getByName("compileKotlinJvm").dependsOn("kspCommonMainKotlinMetadata")
tasks.getByName("compileKotlinMacosX64").dependsOn("kspCommonMainKotlinMetadata")
Use the annotations @Ser
on a class to have serializers generated. The serialization will always pick the constructor with the largest number of arguments and work on it's parameters:
- For deserialization, the detected parameters will be read from the JSON-stream and passed into the constructor to build the object.
- For serialization, the detected parameters will be read from the object, it is necessary to have public field-access for them.
Annotating a class MyClass
with @Ser
will create two extension functions:
JsonReader.nextMyClass(): MyClass
for reading the object from the streamJsonWriter.valueMyClass(myClass: MyClass)
for writing the object to the stream
To support custom types you need to create two extension functions in the same package as the type:
JsonReader.nextMyType(): MyType
for reading the type from the streamJsonWriter.valueMyType(myType: MyType)
for writing the type to the stream
Polymorphism is supported automatically when you annotate an interface using @Ser
. The plugin will find all implementations and write their type and data into an array during serialization and use it during deserialization.
To serialize and deserialize circular structures you need to
- Annotate both parent and child objects using
@Ser
. - Have the parent object passed into the child as a constructor parameter and annotate it using
@ParentRef
. - Have the child object stored in the parent object in a variable
List
or a nullable parameter.
- ENUMs and field names are deserialized case-insensitively, they are serialized with their original case.