Skip to content

juanchurtado1991/ghost-serializer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

327 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ‘» Ghost Serializer

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).

Kotlin KSP Tests Version Android iOS KMP Spring Boot

πŸ‘‰ Try the Interactive Demo β†’ Β Β |Β Β  πŸ“¦ Maven Central β†’ Β· 1.2.7 Β Β |Β Β  πŸ“Š Coverage Report β†’


What makes Ghost different

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.


Demo

▢️ Watch the Demo Video (docs/ghost.mp4) β†’

Real benchmark on Android vs KotlinX Serialization β€” running in the ghost-sample Compose Multiplatform app.


Full Benchmark Results

  • πŸ“Š HTTP Arena Benchmarks β†’ β€” ktor-ghost composite 831 vs plain ktor 728 (+14%); see table above for per-workload RPS.
  • πŸ“ˆ benchmarks.md β€” Full multi-engine tables (Ghost, KSER, Gson, Jackson), stress tests, special-feature benchmarks, run instructions.

πŸ“¦ Quick Start

# 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)

🀝 Zero-Risk: Full Coexistence with your current Serializer

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!

Ktor Setup:

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() 
    }
}

Retrofit Setup:

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()

Spring Boot Setup:

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:

  • Request and response bodies using classes annotated with @GhostSerialization are processed by Ghost for maximum performance.
  • Any other types automatically fall through and are processed by your standard serializer (like Jackson).

No manual configuration is required!


πŸ“¦ Modules at a Glance

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

β†’ Full modules guide β†’


πŸ“š Documentation

Guide Platform / Category Description
Modules & Integrations Modules All artifacts, framework integrations, and platform targets
Installation Setup Version catalog, KSP setup, ghost.textChannel opt-in
Usage β€” Android Android Gradle plugin, Retrofit, Resilience, Custom Decoders
Usage β€” KMP Kotlin Shared module, Ktor, Sealed classes, Structural Transformations
Usage β€” iOS / Swift iOS XCFramework export, Bridge setup, Alamofire integration
Usage β€” Spring Boot Spring Auto-config, MVC + WebFlux, @GhostStrict, @GhostCoerce
Usage β€” Protobuf Core @GhostProtoSerialization, proto3 JSON mapping, Well-Known Types, known limitations
Advanced Features Core Byte-first, @GhostFlatten, @GhostWrap, Contextual Serializers, Platform limits
Type System Types Supported field types, opaque JSON, collections, unsupported patterns
Architecture Design Compiler pipeline, buffer pool mechanics, O(1) bitwise field matching
Benchmarks Speed Full results, run instructions, JIT log analysis
Contributing Community Dev environment, test modules, PR checklist, supported platforms

Related Projects

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

πŸ—οΈ Architecture

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 β†’.


🀝 Contributing

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.


πŸ“„ License

Apache 2.0


Developed with ❀️ by the Ghost Serializer team. πŸ‘»