
High-performance, zero-copy JSON and Proto JSON serializer for Kotlin Multiplatform (KMP) and Ktor, powered by KSP2
Speed up your high-traffic paths by 66% using 50% less memory — without touching your legacy APIs.
Ghost is a byte-first, compile-time JSON serializer designed for Kotlin Multiplatform (Android, iOS, and JVM) that acts as a drop-in optimization. It coexists seamlessly with your existing setup (like kotlinx.serialization, Jackson, or Gson), allowing you to adopt it incrementally in native mobile apps and high-traffic backends (Ktor, Retrofit, Spring Boot).
👉 Try the Interactive Demo →
|
📦 Maven Central → · 1.2.7
Ghost generates all serialization code at compile time via KSP — and then goes several steps further:
| Technique | What it means |
|---|---|
| Bitwise O(1) trie field matching | No string comparison, no heap allocation per field |
Long bitmask for required fields |
Checking all required fields = one CPU instruction |
| Dedicated reader per input format |
ByteArray, Okio stream, String — no cross-format conversion |
| Thread-local reader/writer pools | Zero GC pressure in steady state |
| KSP2 + Kotlin 2.1.10 | Fastest incremental builds, strict compile-time safety |
Result on HTTP Arena Kotlin frameworks (3-framework comparison, composite score). Ghost replaces Ktor's default JSON codec with compile-time serializers and zero-copy parsing — higher throughput on real API workloads with lower memory pressure.
| Framework | Composite | vs plain Ktor | Highlights |
|---|---|---|---|
| ktor-ghost | 831 | +14% composite | JSON TLS +67% RPS · Static +55% · API-16 +9% · Pipelined +3% |
| ktor | 728 | baseline | Default ContentNegotiation + kotlinx.serialization |
| fishcake | 1134 | +56% composite | Different stack (not Ktor); shown for arena context |
| Workload | ktor-ghost RPS | ktor RPS | Δ |
|---|---|---|---|
| JSON TLS | 658k | 395k | +67% |
| Static | 608k | 392k | +55% |
| Short-lived | 622k | 602k | +3% |
| API-16 | 188k | 173k | +9% |
| API-4 | 114k | 104k | +10% |
| Pipelined | 3.48M | 3.15M | +10% |
Source: http-arena.com — Kotlin filter, ktor-ghost vs ktor vs fishcake. Wire Ghost via install(ContentNegotiation) { ghost() } and bodyGhost<T>() / respondGhost() to bypass generic negotiation on hot paths.
Real benchmark on Android vs KotlinX Serialization — running in the
ghost-sampleCompose Multiplatform app.
ktor-ghost composite 831 vs plain ktor 728 (+14%); see table above for per-workload RPS.# gradle/libs.versions.toml
[versions]
ghost = "1.2.7"
ksp = "2.1.10-1.0.31"
[libraries]
ghost-api = { module = "com.ghostserializer:ghost-api", version.ref = "ghost" }
ghost-serialization = { module = "com.ghostserializer:ghost-serialization", version.ref = "ghost" }
ghost-compiler = { module = "com.ghostserializer:ghost-compiler", version.ref = "ghost" }// build.gradle.kts
plugins {
id("com.google.devtools.ksp") version "2.1.10-1.0.31"
id("com.ghostserializer.ghost") version "1.2.7"
}@GhostSerialization
data class User(val id: Long, val name: String, val email: String)
val user: User = Ghost.deserialize(responseBytes) // ByteArray — fastest path
val json: String = Ghost.encodeToString(user)You don't need to rewrite your entire project. Ghost can coexist seamlessly with your existing setup (like kotlinx.serialization, Jackson, or Gson).
If a class does not have the @GhostSerialization annotation, request/response negotiation automatically falls back to your standard serializer. This means you can adopt Ghost incrementally, using it only on your highest-traffic endpoints!
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import com.ghost.serialization.ktor.ghost
import kotlinx.serialization.json.Json
fun Application.module() {
install(ContentNegotiation) {
// 1. Kotlinx.serialization (or Jackson/Gson) handles the standard endpoints
json(Json { ignoreUnknownKeys = true })
// 2. Ghost handles high-performance @GhostSerialization endpoints as fallback
ghost()
}
}import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import com.ghost.serialization.retrofit.GhostConverterFactory
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com")
// 1. GhostConverterFactory handles @GhostSerialization endpoints
.addConverterFactory(GhostConverterFactory.create())
// 2. GsonConverterFactory (or Moshi / Kotlinx.serialization) handles the rest as fallback
.addConverterFactory(GsonConverterFactory.create())
.build()With the ghost-spring-boot-starter dependency added, coexistence is fully automatic. The starter automatically registers GhostHttpMessageConverter (for Spring MVC) and GhostReactiveEncoder/GhostReactiveDecoder (for Spring WebFlux) at the beginning of the message converter/codec chain:
@GhostSerialization are processed by Ghost for maximum performance.No manual configuration is required!
| Module | Artifact | For |
|---|---|---|
| Core |
ghost-api + ghost-serialization
|
Every project — annotations + runtime engine |
| Compiler | ghost-compiler |
KSP code generator (auto-wired by the Gradle plugin) |
| Gradle plugin | com.ghostserializer.ghost |
Auto-configures KSP across all targets |
| Ktor | ghost-ktor |
Ktor 2.3.x client + server |
| Retrofit | ghost-retrofit |
Retrofit 2.11+ Android/JVM |
| Spring Boot | ghost-spring-boot-starter |
Spring Boot 3.4+ auto-config |
| Proto3 | ghost-protobuf |
Proto3 JSON mapping + Well-Known Types |
| Guide | Platform / Category | Description |
|---|---|---|
| Modules & Integrations | ![]() |
All artifacts, framework integrations, and platform targets |
| Installation | ![]() |
Version catalog, KSP setup, ghost.textChannel opt-in |
| Usage — Android | ![]() |
Gradle plugin, Retrofit, Resilience, Custom Decoders |
| Usage — KMP | ![]() |
Shared module, Ktor, Sealed classes, Structural Transformations |
| Usage — iOS / Swift | ![]() |
XCFramework export, Bridge setup, Alamofire integration |
| Usage — Spring Boot | ![]() |
Auto-config, MVC + WebFlux, @GhostStrict, @GhostCoerce
|
| Usage — Protobuf | ![]() |
@GhostProtoSerialization, proto3 JSON mapping, Well-Known Types, known limitations |
| Advanced Features | ![]() |
Byte-first, @GhostFlatten, @GhostWrap, Contextual Serializers, Platform limits |
| Type System | ![]() |
Supported field types, opaque JSON, collections, unsupported patterns |
| Architecture | ![]() |
Compiler pipeline, buffer pool mechanics, O(1) bitwise field matching |
| Benchmarks | ![]() |
Full results, run instructions, JIT log analysis |
| Contributing | ![]() |
Dev environment, test modules, PR checklist, supported platforms |
| Project | Description |
|---|---|
| ghost-sample (this repo) | KMP Compose benchmark app — Android, Desktop JVM, iOS |
| ghost-android-test-app | Standalone Android app — on-device benchmark |
| ghost-ios-test-app | Standalone iOS app — Xcode + XCFramework |
| ghost-spring-boot-test-app | Spring Boot WebFlux dashboard + benchmark.py
|
Ghost uses three reader types and two writer types, all generated by KSP:
Ghost.deserialize<User>(bytes: ByteArray)
└─ GhostJsonFlatReader ← zero alloc, bitwise trie field match
Ghost.deserialize<User>(json: String)
└─ GhostJsonStringReader ← native char[] scan, no encodeToByteArray
Ghost.deserializeStreaming<User>(source: BufferedSource)
└─ GhostJsonReader ← O(1) memory regardless of payload size
Ghost.encodeToBytes(user) → GhostJsonFlatWriter (pre-encoded headers, thread-local pool)
Ghost.encodeToString(user) → FlatCharArrayWriter (pooled, platform-tuned warm capacity)
All paths are fully monomorphic — the JIT compiles them to near-native throughput after warmup.
For a deep dive into the compiler plugin, thread-local buffer pool mechanics, and fast parsing architecture, see the Architecture Guide →.
git clone https://github.com/juanchurtado1991/ghost-serializer.git
./gradlew ciTestJvm # JVM modules (Linux / macOS / Windows)
./gradlew ciTest # + Android unit tests; + iOS on macOS| Requirement | Version |
|---|---|
| JDK | 17 |
| Kotlin / KSP | 2.1.10 / 2.1.10-1.0.31 |
| Android SDK | API 36 (for unit tests) |
→ Full contributing guide → — dev environment, adding test modules, benchmarks, PR checklist.
See CHANGELOG.md for version history.
Developed with ❤️ by the Ghost Serializer team. 👻
Speed up your high-traffic paths by 66% using 50% less memory — without touching your legacy APIs.
Ghost is a byte-first, compile-time JSON serializer designed for Kotlin Multiplatform (Android, iOS, and JVM) that acts as a drop-in optimization. It coexists seamlessly with your existing setup (like kotlinx.serialization, Jackson, or Gson), allowing you to adopt it incrementally in native mobile apps and high-traffic backends (Ktor, Retrofit, Spring Boot).
👉 Try the Interactive Demo →
|
📦 Maven Central → · 1.2.7
Ghost generates all serialization code at compile time via KSP — and then goes several steps further:
| Technique | What it means |
|---|---|
| Bitwise O(1) trie field matching | No string comparison, no heap allocation per field |
Long bitmask for required fields |
Checking all required fields = one CPU instruction |
| Dedicated reader per input format |
ByteArray, Okio stream, String — no cross-format conversion |
| Thread-local reader/writer pools | Zero GC pressure in steady state |
| KSP2 + Kotlin 2.1.10 | Fastest incremental builds, strict compile-time safety |
Result on HTTP Arena Kotlin frameworks (3-framework comparison, composite score). Ghost replaces Ktor's default JSON codec with compile-time serializers and zero-copy parsing — higher throughput on real API workloads with lower memory pressure.
| Framework | Composite | vs plain Ktor | Highlights |
|---|---|---|---|
| ktor-ghost | 831 | +14% composite | JSON TLS +67% RPS · Static +55% · API-16 +9% · Pipelined +3% |
| ktor | 728 | baseline | Default ContentNegotiation + kotlinx.serialization |
| fishcake | 1134 | +56% composite | Different stack (not Ktor); shown for arena context |
| Workload | ktor-ghost RPS | ktor RPS | Δ |
|---|---|---|---|
| JSON TLS | 658k | 395k | +67% |
| Static | 608k | 392k | +55% |
| Short-lived | 622k | 602k | +3% |
| API-16 | 188k | 173k | +9% |
| API-4 | 114k | 104k | +10% |
| Pipelined | 3.48M | 3.15M | +10% |
Source: http-arena.com — Kotlin filter, ktor-ghost vs ktor vs fishcake. Wire Ghost via install(ContentNegotiation) { ghost() } and bodyGhost<T>() / respondGhost() to bypass generic negotiation on hot paths.
Real benchmark on Android vs KotlinX Serialization — running in the
ghost-sampleCompose Multiplatform app.
ktor-ghost composite 831 vs plain ktor 728 (+14%); see table above for per-workload RPS.# gradle/libs.versions.toml
[versions]
ghost = "1.2.7"
ksp = "2.1.10-1.0.31"
[libraries]
ghost-api = { module = "com.ghostserializer:ghost-api", version.ref = "ghost" }
ghost-serialization = { module = "com.ghostserializer:ghost-serialization", version.ref = "ghost" }
ghost-compiler = { module = "com.ghostserializer:ghost-compiler", version.ref = "ghost" }// build.gradle.kts
plugins {
id("com.google.devtools.ksp") version "2.1.10-1.0.31"
id("com.ghostserializer.ghost") version "1.2.7"
}@GhostSerialization
data class User(val id: Long, val name: String, val email: String)
val user: User = Ghost.deserialize(responseBytes) // ByteArray — fastest path
val json: String = Ghost.encodeToString(user)You don't need to rewrite your entire project. Ghost can coexist seamlessly with your existing setup (like kotlinx.serialization, Jackson, or Gson).
If a class does not have the @GhostSerialization annotation, request/response negotiation automatically falls back to your standard serializer. This means you can adopt Ghost incrementally, using it only on your highest-traffic endpoints!
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import com.ghost.serialization.ktor.ghost
import kotlinx.serialization.json.Json
fun Application.module() {
install(ContentNegotiation) {
// 1. Kotlinx.serialization (or Jackson/Gson) handles the standard endpoints
json(Json { ignoreUnknownKeys = true })
// 2. Ghost handles high-performance @GhostSerialization endpoints as fallback
ghost()
}
}import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import com.ghost.serialization.retrofit.GhostConverterFactory
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com")
// 1. GhostConverterFactory handles @GhostSerialization endpoints
.addConverterFactory(GhostConverterFactory.create())
// 2. GsonConverterFactory (or Moshi / Kotlinx.serialization) handles the rest as fallback
.addConverterFactory(GsonConverterFactory.create())
.build()With the ghost-spring-boot-starter dependency added, coexistence is fully automatic. The starter automatically registers GhostHttpMessageConverter (for Spring MVC) and GhostReactiveEncoder/GhostReactiveDecoder (for Spring WebFlux) at the beginning of the message converter/codec chain:
@GhostSerialization are processed by Ghost for maximum performance.No manual configuration is required!
| Module | Artifact | For |
|---|---|---|
| Core |
ghost-api + ghost-serialization
|
Every project — annotations + runtime engine |
| Compiler | ghost-compiler |
KSP code generator (auto-wired by the Gradle plugin) |
| Gradle plugin | com.ghostserializer.ghost |
Auto-configures KSP across all targets |
| Ktor | ghost-ktor |
Ktor 2.3.x client + server |
| Retrofit | ghost-retrofit |
Retrofit 2.11+ Android/JVM |
| Spring Boot | ghost-spring-boot-starter |
Spring Boot 3.4+ auto-config |
| Proto3 | ghost-protobuf |
Proto3 JSON mapping + Well-Known Types |
| Guide | Platform / Category | Description |
|---|---|---|
| Modules & Integrations | ![]() |
All artifacts, framework integrations, and platform targets |
| Installation | ![]() |
Version catalog, KSP setup, ghost.textChannel opt-in |
| Usage — Android | ![]() |
Gradle plugin, Retrofit, Resilience, Custom Decoders |
| Usage — KMP | ![]() |
Shared module, Ktor, Sealed classes, Structural Transformations |
| Usage — iOS / Swift | ![]() |
XCFramework export, Bridge setup, Alamofire integration |
| Usage — Spring Boot | ![]() |
Auto-config, MVC + WebFlux, @GhostStrict, @GhostCoerce
|
| Usage — Protobuf | ![]() |
@GhostProtoSerialization, proto3 JSON mapping, Well-Known Types, known limitations |
| Advanced Features | ![]() |
Byte-first, @GhostFlatten, @GhostWrap, Contextual Serializers, Platform limits |
| Type System | ![]() |
Supported field types, opaque JSON, collections, unsupported patterns |
| Architecture | ![]() |
Compiler pipeline, buffer pool mechanics, O(1) bitwise field matching |
| Benchmarks | ![]() |
Full results, run instructions, JIT log analysis |
| Contributing | ![]() |
Dev environment, test modules, PR checklist, supported platforms |
| Project | Description |
|---|---|
| ghost-sample (this repo) | KMP Compose benchmark app — Android, Desktop JVM, iOS |
| ghost-android-test-app | Standalone Android app — on-device benchmark |
| ghost-ios-test-app | Standalone iOS app — Xcode + XCFramework |
| ghost-spring-boot-test-app | Spring Boot WebFlux dashboard + benchmark.py
|
Ghost uses three reader types and two writer types, all generated by KSP:
Ghost.deserialize<User>(bytes: ByteArray)
└─ GhostJsonFlatReader ← zero alloc, bitwise trie field match
Ghost.deserialize<User>(json: String)
└─ GhostJsonStringReader ← native char[] scan, no encodeToByteArray
Ghost.deserializeStreaming<User>(source: BufferedSource)
└─ GhostJsonReader ← O(1) memory regardless of payload size
Ghost.encodeToBytes(user) → GhostJsonFlatWriter (pre-encoded headers, thread-local pool)
Ghost.encodeToString(user) → FlatCharArrayWriter (pooled, platform-tuned warm capacity)
All paths are fully monomorphic — the JIT compiles them to near-native throughput after warmup.
For a deep dive into the compiler plugin, thread-local buffer pool mechanics, and fast parsing architecture, see the Architecture Guide →.
git clone https://github.com/juanchurtado1991/ghost-serializer.git
./gradlew ciTestJvm # JVM modules (Linux / macOS / Windows)
./gradlew ciTest # + Android unit tests; + iOS on macOS| Requirement | Version |
|---|---|
| JDK | 17 |
| Kotlin / KSP | 2.1.10 / 2.1.10-1.0.31 |
| Android SDK | API 36 (for unit tests) |
→ Full contributing guide → — dev environment, adding test modules, benchmarks, PR checklist.
See CHANGELOG.md for version history.
Developed with ❤️ by the Ghost Serializer team. 👻