Releases: juanchurtado1991/ghost-serializer
Release list
Ghost Serializer 1.3.1
Highlights
YAML compliance ~96%
Ghost YAML is now measured against the yaml-test-suite with a full offline harness (yamlComplianceMatrix).
- Reader compliance: ~54% → 96.06% (151 → 268 of 279 valid cases with a JSON fixture — same denominator as matrix.yaml.info; 1.3.0 shipped YAML before the suite was measured)
- Dozens of real parser bugs fixed (anchors/aliases, tags, block scalars, flow collections, comments, tabs, explicit keys, multi-line plain scalars, and silent wrong-tree cases)
- Writer round-trip: 100% (321/321); remaining kaml-oracle gaps are oracle limitations, not Ghost bugs
- Known remaining gaps are tracked by case ID in
YamlTestSuiteDeviations.kt(no silent skips) - New YAML + JSON coverage-guided fuzzing (Jazzer) in the JVM CI path
Safari / Wasm Speed Test (#16)
On JavaScriptCore (Safari / iOS), Ghost.encodeToString no longer collapses on CharArray.concatToString.
- JSC path: UTF-8 flat writer + browser
TextDecoder - Chrome / V8: keeps the char writer (already fast)
- Safari string Speed Test after fix: ~2.7× kotlinx.serialization
- JVM / Android / Native unchanged
Also in 1.3.1
- Spring + Retrofit collection bodies: top-level
List/Set/Mapunwrap (MVC + WebFlux, JSON + YAML); fix forList<String>/Map<String, String>falling through to Jackson - WKT string-channel overrides: nested Well-Known Types under
textChannel = trueavoid a full UTF-8 bridge + reparse - Hot-path allocation fixes: digit-walk HOFs no longer allocate on synthetic decode;
SetSerializerresilient path avoids double allocation Ghost.deserialize(bytes) { options }now uses the flat reader (same engine as plaindeserialize(bytes))- Study manual regenerated:
docs/Ghost-Serialization-Manual-1.3.1.pdf
Install
implementation("com.ghostserializer:ghost-serialization:1.3.1")Gradle plugin: com.ghostserializer.ghost version 1.3.1
Full notes: CHANGELOG.md
👻 Ghost Serializer 1.3.0 — Unified JSON + YAML + Proto3 JSON runtime
This isn't an incremental bump from 1.2.7 — it's a rewrite of what "Ghost" ships as an artifact, plus the biggest decode-throughput jump in the project's history.
Highlights
- 🔀 One runtime, three wire formats. JSON, YAML, and Proto3 JSON now live in a single
ghost-serializationartifact.ghost-yaml,ghost-yaml-ktor, andghost-protobufare gone. - ⚡ Decode throughput up to 1.2 GB/s. A rewritten decode hot path (in-order field prediction + SWAR scanning) pushed every channel well past 1.2.7 — String decode crosses 1 GB/s for the first time.
- 🌐 Kotlin/Wasm everywhere.
ghost-api,ghost-serialization,ghost-ktor, and the new Ghost Playground now shipwasmJstargets alongside JVM/Android/iOS. - 🕹️ New Ghost Playground — Compose Multiplatform (JVM + Wasm) site with a live JSON/YAML/Proto Studio and a browser speed test vs
kotlinx.serializationand Moshi. - 🐛 Two silent data-corruption bugs fixed in the streaming reader and the WebFlux NDJSON decoder.
⚡ Performance: crossing 1 GB/s
Twitter macro fixture (631,514 bytes). Same 3 decode channels:
| Decode | 1.2.7 | 1.3.0 | Δ 1.2.7→1.3.0 | vs KSER | vs Moshi |
|---|---|---|---|---|---|
| String | 0.803 GB/s | 1.229 GB/s · 514 µs/op | +53% | +71% | +229% |
| Bytes | 0.698 GB/s | 1.052 GB/s · 600 µs/op | +51% | +148% | +283% |
| Streaming | 0.304 GB/s | 0.529 GB/s · 1194 µs/op | +74% | +174% | +24% |
(1.2.7 GB/s derived from its own published ops/s × the 631,514-byte Twitter fixture — same fixture in both versions; 1.2.7 didn't track GB/s directly.)
Three profile-driven changes got us here, each A/B-verified and kept only when it won:
- In-order field prediction — machine-generated JSON lists fields in declaration order, so the reader checks the predicted next field first instead of hashing every key. Biggest single win.
- SWAR whitespace + key comparison — 8 bytes at a time (
VarHandlewide load on JVM, scalar SWAR elsewhere). - SWAR value-string scan with deferred pool hash — branch-free 8-byte scan for quotes/backslash/control/non-ASCII; the string-pool hash is now only computed for strings short enough to actually pool.
Encode got targeted wins too (ASCII-prefix fast path +10%, BMP Unicode fast path +13% on the string channel). Full multi-engine tables: benchmarks.md.
🔀 Unified runtime: JSON + YAML + Proto3 JSON
1.2.7 shipped three separate artifacts. 1.3.0 merges them into ghost-serialization:
// Before (1.2.x)
implementation("com.ghostserializer:ghost-yaml:1.2.x")
implementation("com.ghostserializer:ghost-yaml-ktor:1.2.x")
implementation("com.ghostserializer:ghost-protobuf:1.2.x")
// After — one runtime artifact
implementation("com.ghostserializer:ghost-serialization:1.3.0")
implementation("com.ghostserializer:ghost-ktor:1.3.0") // JSON + YAML + Proto adaptersOr apply id("com.ghostserializer.ghost") version "1.3.0" and let the Gradle plugin auto-inject adapters.
Full diff: v1.2.7...v1.3.0
Ghost Serialization v1.2.7
Production-ready, zero-allocation serialization engine for Kotlin Multiplatform. This release introduces support for Proto3 JSON mapping, brings robust HTTP integrations for Ktor, Retrofit, and Spring Boot, adds coverage-guided fuzz testing, and fixes critical edge-case serialization bugs.
📦 New Module: ghost-protobuf
We have introduced a new Kotlin Multiplatform module (com.ghostserializer:ghost-protobuf) which layers Proto3 JSON mapping rules on top of the zero-allocation JSON engine.
- Multiplatform Targets: Android, iOS (Arm64 & Simulator), and JVM.
- Well-Known Types (WKTs): Zero-allocation serializers for
ProtoDuration,ProtoTimestamp(nanosecond precision, RFC3339 compliant),ProtoStruct,ProtoValue,ProtoAny, and scalar wrapper types (ProtoBoolValue,ProtoInt32Value, etc.). - Any Type Registry: Resolve
ProtoAnydynamically viaProtoAnyRegistryusing Ghost’s serializer registry. - Quotations & Unsigned Numeric Ranges: Unsigned 64-bit integer (
uint64) backing viaULongwith correct string quoting and boundaries support.
⚡ ProtoLab Benchmark (Sample App)
Added a new interactive UI page to the sample app to compare performance under real-world scenarios (using OpenLibrary API payloads) between:
- Ghost Core JSON
- Ghost Proto3 JSON
- KotlinX Serialization (Standard JSON & Proto3 JSON)
🔗 Framework Integrations
- Spring Boot Starter:
GhostHttpMessageConverternow auto-detects classes annotated with@GhostProtoSerializationand routes them dynamically through theGhostProtoJsonFlatReader. - Ktor Content Negotiation: Added
GhostProtoContentConverteralongside bypass helpers (bodyGhostProto(),respondGhostProto()). - Retrofit Client: Added
GhostProtoConverterFactoryfor directly reading Proto3 JSON payloads.
🛠️ Bug Fixes & Conformances
- Validation against Reference Implementation: Introduced
ProtoJsonConformanceTestcross-checking output against Google'sprotobuf-javaJsonFormat.Printerto ensure 100% compliance. - Fixed Sign Loss on Durations: Fixed an issue where negative durations under one second (e.g.,
-0.5s) lost their sign. - Long.MIN_VALUE Edge Case: Corrected negative space overflow in boundary numeric conversions that previously corrupted
Long.MIN_VALUEinto"-0". - Fractional Seconds Widths:
DurationandTimestampnow correctly pad fractional seconds to exactly 3, 6, or 9 digits as required by the Proto3 JSON specification. - Base64 Out-of-Bounds: Fixed potential
ArrayIndexOutOfBoundsExceptionwhen parsing invalid Base64 streams with non-Latin-1 characters.
💡 API & Internals Changes
- Subclassing Support: Opened
GhostJsonFlatReaderfor extension so that custom/protocol-specific readers (likeGhostProtoJsonFlatReader) can override parsing behavior without duplicating the buffer implementation. - CI Stability: Resolved a CI Gradle runner GPG signing exception during JVM unit test suites on host-clean runners.
👻 Ghost Serializer — Release v1.2.4 (Hotfix)
We are releasing v1.2.4 as an urgent hotfix addressing critical compilation and runtime crashes when matching JSON field names. All users are strongly encouraged to upgrade immediately.
🚀 What's Fixed
Perfect Hash Collision Resolution in KSP & Runtime (Issue #10)
Previously in v1.2.3 and below, classes containing properties of the exact same character length that also shared overlapping prefixes/suffixes (e.g., modelCode vs modelName, dateCreated vs dateUpdated, or inviterUsername vs inviteeUsername) could trigger identical key hashes in the perfect hashing algorithm.
This resulted in:
- Compile-time KSP failures due to the generator being unable to resolve a collision-free multiplier.
- Runtime deserialization crashes (
GhostJsonException: Expected '"') or silent data mapping corruption when fields resolved to the same slot during O(1) matching.
How we fixed it:
We refactoredPerfectHashFinder(compiler) andJsonReaderOptions(runtime) to utilize a zero-allocation polynomial accumulationwhileloop (hash multiplier of 31) over all remaining bytes of the field name upon detecting a collision. This completely resolves collision overlapping, guaranteeing correct field dispatch with zero extra memory overhead.
📦 Dependency Info
[versions]
ghost = "1.2.4"
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" }plugins {
id("com.google.devtools.ksp") version "2.1.10-1.0.31"
id("com.ghostserializer.ghost") version "1.2.4"
}👻 Ghost Serializer v1.2.3
We are excited to announce the release of Ghost Serializer v1.2.3! This version introduces massive memory footprint optimizations for small/medium models, native Android UI thread pooling enhancements, native ByteArray support, and resolves several compiler edge-cases and limits.
Our complete Kotlin Multiplatform verification suite has grown to 825/825 passing tests!
⚡ Performance & Memory Optimizations
- Dynamic Perfect Hash Table Sizing: Instead of allocating a fixed
1024-size dispatch table for every class, the compiler now starts searching for a collision-free perfect hash at size128and scales up (256,512,1024, etc.) only on demand. This reduces the runtime memory footprint of the dispatch table by 50% to 87.5% for small and medium-sized models. - Android ThreadLocal UI Thread Bypass: Optimized
getLocalPool()on Android. By caching the main UI thread reference on first access and performing a fast identity comparison (===), we now completely bypass theThreadLocal.get()map lookup on the UI thread. - String Pool Cache Locality: Added a contiguous primitive
IntArray(stringPoolHashes) to bothGhostJsonFlatReaderandGhostJsonStringReader. This keeps string pool miss lookups inside the CPU's L1 data cache and avoids dereferencing coldStringobject references.
🛠️ Bug Fixes
- Perfect Hash Table Scaling for Large Models: Refactored
PerfectHashFinder.ktandJsonReaderOptions.ktto support dynamic table sizes up to8192. This resolves KSP processing failures for large models (like the 100-fieldCollisionModel) that could not find a perfect hash at the default size. - Android JVM Unit Test Looper Mocking: Wrapped
Looper.getMainLooper()inGhostPools.android.ktin atry-catchblock to preventMethod getMainLooper in android.os.Looper not mockedcrashes when executing Android unit tests in a pure JVM environment. classDeclarationInaccessible inGhostCodeGenerator: Declared theclassDeclarationconstructor parameter as aval, making it visible to annotation-reading helpers insidebuildSerializerObject().@GhostFallbackSupport for Enum Deserialization: Enums annotated with@GhostFallbackno longer throwGhostJsonExceptionon an unrecognized ordinal. The compiler now reads the annotation and emits anelse ->branch pointing to the marked fallback constant.- Auto-
UNKNOWNFallback for Enums: If an enum class has a constant namedUNKNOWN(any case variation), the compiler now automatically generates a fallback to it without requiring the@GhostFallbackannotation. - KSP Duplicate Property Collection on Interface/Superclass Override (Issue #4):
getAllProperties()returns both the original and the overriding declaration when a data class overrides an interface property, causing the same JSON field to be registered twice. Fixed by filtering out any property for whichfindOverridee()returns a non-null result before building property models. StackOverflowErrorinemitFlattenedGroupon Path-Length Mismatch (Issue #5): When colliding@GhostFlatten/@WrappedKeyspaths have different depths,pathIndexcould exceed the shorter path's length, leading to infinite recursion. Fixed by using>=for the single-property leaf termination check and adding an explicit guard that throws a clearIllegalStateException.
➕ Added
ByteArrayField Type Support: Fields declared asByteArrayare now serialized by writing the pre-encoded bytes directly into the JSON stream viarawValue(), and deserialized by capturing the raw token span viacaptureRawJsonBytes(). AddsGhostJsonReaderCapture,GhostJsonFlatReaderCapture, andGhostJsonStringReaderCapturefor all three reader flavors.
📦 Installation (Gradle)
plugins {
id("com.google.devtools.ksp") version "2.1.10-1.0.31"
id("com.ghostserializer.ghost") version "1.2.3"
}
dependencies {
// Core Runtime & Platform Adapters
implementation("com.ghostserializer:ghost-serialization:1.2.3")
implementation("com.ghostserializer:ghost-ktor:1.2.3")
implementation("com.ghostserializer:ghost-retrofit:1.2.3")
}Ghost Serialization v1.2.2
👻 Ghost Serialization v1.2.2 — Kotlin 2.1.10, KSP2 Support & Single-Pass Optimization
We are thrilled to release v1.2.2 of Ghost Serialization! This release brings full compatibility with Kotlin 2.1.10 and KSP2, alongside key performance optimizations that solidify Ghost as the fastest JSON engine for Kotlin Multiplatform.
With these updates, Ghost sweeps 1st place in all 6 JSON benchmark categories (Decode/Encode × String/Bytes/Streaming) on the Twitter macro dataset.
⚡ Key Highlights
- Kotlin 2.1.10 & KSP2 Support: Complete migration to KSP
2.1.10-1.0.31with KSP2 enabled (ksp.useKSP2=true) for faster incremental compiler builds. - Single-Pass String Scan (
GhostJsonStringReader): Combines key boundary detection and perfect hashing in a single unrolled loop over raw memory, cutting key-matching memory reads in half. - Zero-Allocation String Decoding: Replaces array allocation routines with intrinsic character access (
rawData[index].code), boosting String decoding performance to +32.1% faster than Kotlinx Serialization (KSer) with 69.6% less memory. - Ktor Server & Client Extensions: Integrated direct byte-first
respondGhost(Server) andbodyGhost(Client) functions to bypass Ktor pipeline overhead entirely.
📋 Full Changelog
🚀 Performance
- Single-Pass String Scan: Eliminated a redundant double-scan in the hot path of
internalSelect. The newfindClosingQuoteWithHashcombines locating the closing quote and computing the 4-byte dispatch hash into a single loop, cutting key matching reads in half.
🛠️ Optimizations
- Adapter Integration (Ktor, Retrofit, Spring Boot): Migrated Ktor, Retrofit, and Spring Boot adapters to use the new cached-serializer public APIs (
Ghost.encodeToBytesandGhost.deserialize), removing internal overhead. - RandomAccess List Loops: Replaced default
Iterator-based loops with index-based loops inListSerializer,IntArraySerializer, andLongArraySerializerforRandomAccesscollections (likeArrayList) to avoid iterator heap allocations under heavy loops. - Map Entry-Set Iteration: Optimized
MapSerializerto iterate entries directly instead of performing double hash lookups via key sets. - Fast-Path ASCII String Writer Scans: Refactored ASCII scans in
GhostJsonStringWriterwith hoisted local registers for native bulk copying. - Dynamic String Writer Heap Sizing: Reduced the default initial capacity of
FlatCharArrayWriterfrom 8 KB to 1 KB (2 KB heap) and fine-tuned mobile buffer retention heuristics to lower memory footprint on Android and iOS. - Streaming Segment-Buffering: Implemented an internal 8 KB segment buffer directly in
StreamingGhostSourceto copy and hold active Okio segments, bypassing virtual dispatch.
✨ Added
- Ktor Server & Client Direct Serialization: Added high-performance
respondGhost(Server) andbodyGhost(Client) extensions, bypassing Ktor'sContentNegotiationpipeline. - Cached Serializer Overloads: Exposed new public overloads for
encodeToString,encodeToBytes,deserialize, anddeserializeStreamingthat accept pre-resolvedGhostSerializer<T>parameters. - Native String Reader Opt-in (
ghost.textChannel):GhostJsonStringReaderoverloads are now opt-in via KSP configuration. When disabled (default), the string dispatch table is omitted, saving 4 KB of memory per DTO.
🧹 Refactored
- Zero Magic Strings & Numbers: Centralized all template strings, error messages, and control identifiers into
GhostEmitterConstantsandGhostJsonConstants. - KMP Deprecations Cleanup: Replaced deprecated platform constructors with standard Kotlin Multiplatform
CharArray.concatToString().
📦 Quick Start
# gradle/libs.versions.toml
[versions]
ghost = "1.2.2"
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" }Ghost Serialization 1.2.1
This release resolves a critical class-loading NullPointerException during cold-start JIT prewarming, introduces detailed memory profiling (KB/op) using ThreadMXBean into the Twitter macro-dataset benchmarks, and establishes automated deep-equivalence validation guaranteeing 100% data fidelity with zero-data-loss serialization roundtrips.
🚀 What's New
🛠️ Twitter Macro-Dataset Memory Profiling
- Twitter Benchmark Memory Metrics: Integrated JVM
ThreadMXBeanmemory tracking to profile real-time allocated memory per operation (KB/op) in the Twitter Macro Dataset benchmark.💡 Highlight: Demonstrates up to 6.5x memory reduction when using direct bytes.
- Special Features Twitter Tests: Included new integration tests verifying Ghost's advanced structural features (
@GhostFlatten,@GhostWrap, and@GhostIgnore) directly on Twitter-like production payloads with flawless serialization roundtrips.
🛠️ What's Changed
🛡️ Core Stability & Class-Loading Fixes
- Contextual Serializers Class-Loading NullPointerException: Resolved a critical
NPEduring class initialization of KSP-generated serializers (likeContextualModelSerializer). WhenGhost.prewarm()loaded the default registry, serializers containing external types loaded their static fields early and threw NPEs if their contextual serializers weren't already registered.Fix: Added support for the pre-registration of manual registries before calling
Ghost.prewarm().
⚙️ Twitter Benchmark Refactoring
- Twitter Benchmark Codebase Refactoring: Refactored the benchmark suite by cleanly extracting configurations, engines, data models, and the Twitter macro benchmark into BenchmarkModels.kt and TwitterBenchmark.kt, dramatically reducing the size of GhostBenchmark.kt and removing all compiler warnings.
- 100% Data Fidelity Guarantee: Added robust, automated deep-equivalence testing (
GhostTwitterReproductionTest.kt) verifying 100% exact structural parity with Kotlinx Serialization and complete zero-data-loss serialization roundtrips over the entire Twitter macro dataset.
📚 Documentation
- Best Practices: Updated
README.mdandCHANGELOG.mdwith complete guides on The Byte-First Philosophy (advocating direct byte-array parsing in network layers over UTF-16 String conversions to achieve up to 65% faster deserialization and 6.5x memory reduction). - Roadmap: Added detailed explanations of streaming decode trade-offs and outlined upcoming segment-buffering solutions.
Ghost Serialization 1.2.0 Latest
This release introduces native, declarative network annotations (@GhostStrict and @GhostCoerce) across all major HTTP integrations (Retrofit, Spring Boot, and Ktor), implements critical security and boundary bug fixes with zero-allocation performance preservation, and recovers maximum lenient parsing throughput by default in all network adapters.
🚀 What's New
🛠️ Declarative Network Customization
- Native Declarative Annotations (
@GhostStrict&@GhostCoerce): Shipped new dynamic annotations for elegant, declarative, and zero-allocation parsing customization:- Retrofit: Fully supports
@GhostStrictand@GhostCoerceon API service interface methods to customize parser configurations dynamically per endpoint. - Spring Boot (Spring WebMvc): Integrates native thread-safe annotation scanning using
RequestBodyAdvice. Supports@GhostStrictand@GhostCoerceat the controller class, endpoint method, or@RequestBodyparameter levels out-of-the-box. - Ktor (KMP): Enhanced the
GhostContentConverteringhost-ktorwith a customconfigurerlambda parameter, enabling developers to dynamically tune or enforce strict/coerced settings directly in their KMPContentNegotiationpipelines.
- Retrofit: Fully supports
🛠️ What's Changed
🛡️ Core Security & Resilience Fixes
- Scientific Notation Exponent Integer Overflow: Fixed a vulnerability in
parseExponentValuefor flat and streaming readers by clamping exponent values exceeding1000to prevent integer overflows. - Geometric Capacity Overflow Protection: Fixed a potential buffer overflow vulnerability in
FlatByteArrayWriter.ensureCapacityby safely catching integer overflows and clamping growth boundaries toInt.MAX_VALUE. - Dynamic Key Hash Collision mixing: Eliminated perfect hash collision vulnerabilities in
JsonReaderOptionsand reader subsystems by dynamically detecting perfect key collisions at initialization and conditionally applying a branchless last-byte mix. - Serializer Delegation Config Preservation: Fixed a configuration propagation leak in the
GhostSerializer.deserialize(GhostJsonFlatReader)default delegation method by copying all configuration attributes (e.g.strictMode,coerceStringsToNumbers) to the delegated streaming reader. - Negative Depth Boundary Safety: Protected reader depth decrement operations in
endObject()andendArray()to stay non-negative, preventing bitmask corruption under malformed or resilient parsing. - Unbounded Surrogate Parser Checks: Fixed a boundary bug in
GhostJsonReaderandGhostJsonFlatReaderStringswhere checking for trailing unicode surrogate pairs at the end of truncated strings causedIndexOutOfBoundsExceptioninstead of structuredGhostJsonException. - Long Overflow Check: Fixed a silent overflow bug in
calculateLongWithOverflowCheckwhere values matchingLong.MIN_VALUEwith additional trailing digits bypassed overflow verification.
⚙️ Parser & Writer Correctness
- Strict Comma Validation: Enforced strict JSON comma checking in both streaming and flat readers using zero-allocation bitwise mask tracking. Bound strictly to
strictMode = trueto preserve maximum lenient parsing speed by default. - Iterative Comma Synchronization in
hasNext(): Fixed a critical parser state leak inhasNext()wherecommaConsumedMaskandneedsCommaMaskwere not correctly cleared and tracked during iterative loops likeskipValue(). - Select Separator Comma Synchronization: Fixed
internalSelectin both flat and streaming readers to correctly synchronize and clearcommaConsumedMaskwhen a separator comma is consumed, resolving unexpected comma errors in subsequent field decodes. - Strict Byte Checking: Resolved a project rule violation in
expectByteby replacing the prohibitedtoChar()extension method with the directChar(expected)constructor path. - Negative Zero Sign Loss: Corrected double formatting in
GhostDoubleFormatterto preserve the minus sign for-0.0by performing a zero-copy raw bits sign check. - Double Formatter Precision Threshold: Lowered
MASSIVE_DOUBLE_THRESHOLDfrom1e15to1e9inGhostDoubleFormatterto guarantee standard-compliant shortest representation. - Leading Zero Shift Masking: Corrected a shift-masking bug in
validateLeadingZerowhere non-digit characters in the ASCII range of112..121were validated as digits. - Flat Writer Infinite Loop: Fixed an infinite loop in
ensureCapacitywhenFlatByteArrayWriterwas initialized with zero capacity. - Primitive Collection Doubling: Fixed an
ArrayIndexOutOfBoundsExceptioninGhostIntListandGhostLongListwhen initialized with zero capacity.
⚡ Performance & Allocation Optimization
- Zero-Allocation Stream Decoding: In
StreamingGhostSource.decodeToString, eliminated a temporaryBufferallocation and segment copy. Now leverages Okio'ssnapshot(end).substring(start, end).utf8()directly, resulting in zero-copy range views of existing buffered segments. - Pool Tier Collision: Resolved a collision in
GhostPools.ktwhereSCRATCH_BUFFER_SIZE(48 bytes) andTIER_SMALL(1024 bytes) shared the same pool slot. Added a dedicatedscratchfield toGhostPoolto prevent buffer eviction leaks.
🐘 Compiler (KSP) & Gradle
- Non-Nested Sealed Subclasses: Enhanced KSP generation to scan
superTypesfor sealed parents. This ensures that non-nested/top-level sealed subclasses correctly serialize and deserialize their type discriminator key. - Gradle Plugin KSP Setup Order: Refactored KSP compiler dependency injection in the Gradle plugin to be completely order-independent and reactive to KSP and KMP target application sequences.
📚 Documentation
- Updated
README.mdandCHANGELOG.mdwith complete usage guides, annotations targets, and configuration examples for Retrofit, Spring Boot, and Ktor.
Ghost Serialization 1.1.19
This release brings important fixes to compiler code generation (KSP) and Gradle configurations, ensuring cleaner generated code with zero name-shadowing warnings, fixing redundant assertions, and streamlining Multiplatform Gradle setups.
🛠️ What's Changed
⚙️ Compiler & Code Generation (KSP)
subIndexname shadowing eliminated: In generated serializers for models using nested@GhostFlattenstructures, the recursive generator (emitFlattenedGroup) now dynamically appends the recursion depth to local iteration variables (subIndex0,subIndex1, etc.). This resolves Kotlin compiler warnings about shadowed names.- Redundant non-null assertion (
!!) removed: Removed!!from the copy template blockTEMPLATE_IF_NOT_NULL_COPY(if (v0 != null) instance = instance.copy(...)), resolving redundant assertion warnings on non-null receivers when copying generated structures. - Cleaner compiler output: Demoted custom coder warnings from KSP (
Detected custom coder for...) to informational logs (logger.info), reducing noise during standard Gradle builds.
🐘 Gradle & Multiplatform (KMP)
- Automatic hierarchy template applied: Standardized multiplatform source-set wiring in
ghost-serialization/build.gradle.ktsusingapplyDefaultHierarchyTemplate(). This resolves the target configuration warning introduced in recent Kotlin Multiplatform updates and removes conflicting manualdependsOnstructures for intermediate targets likenativeMainoriosMain.
📚 Documentation
- Updated
GHOST_MANUAL_EN.mdreferences and regenerated the manual PDF build script settings to point to1.1.19. - Bumped standard fallback version in the Gradle plugin to
1.1.19.
Ghost Serialization 1.1.18
What's Changed
Refactoring — KSP Compiler
- Serialization pipeline decomposed into dedicated modules mirroring the deserialization split from 1.1.16:
BaseSerializeEmitter— shared property / collection / value-class emit logicStandardSerializeEmitter— objects with < 40 propertiesFragmentedSerializeEmitter— chunked emission for large models
PerfectHashFinderextracted — compile-time brute-force hash optimizer now lives in its ownobject, with a full runtime walkthrough in KDocFlattenOptionsGeneratorextracted — recursive nested-options generation for@GhostFlattenis now isolated, removing quadratic path-lookup overhead fromGhostCodeGenerator- Cleaner generated variable names — removed leading underscore prefix from generated locals and mask fields:
_result→result,_mask0→mask0,_fieldName→fieldNameValue. Eliminates Kotlin name-shadowing lint warnings in generated code - Bitmask literals hoisted to
private const val—MASK_FIELDNAME/MASK_DEFAULTS_Ncompanion constants replace inline1L shl Nmagic numbers, improving JIT friendliness validateRequiredFieldshelper — required-field validation extracted into a dedicated inline function in generated serializers- Dead constant cleanup in
GhostEmitterConstants— 14 unused constants removed; new constants added for 1.1.18 emission patterns TypeHelpersKDoc pass — all extension functions now have individual KDoc comments
Changed
Ghost.deserialize(BufferedSource)rewritten to useacquireScratchBuffer/releaseScratchBufferinstead of the removedGhostPayloadhelper — zero extra allocations- Removed deprecated aliases
Ghost.serializeToBytes()andGhost.serializeToString()— useencodeToBytes()/encodeToString()directly - Gradle plugin
DEFAULT_VERSIONbumped to1.1.18
Documentation
- Full KDoc added to
Ghost,GhostRegistry,GhostJsonException,JsonReaderOptions,InternalGhostApi, andGhostDoubleFormatter(complete algorithm walkthrough) - API Reference appendix added to the English manual covering all public types and methods
- PDF manual regenerated →
Ghost-Serialization-Manual-1.1.18.pdf(46 pages) - Build scripts added under
scripts/for reproducible PDF generation
Fixed
- CI — iOS:
test-iosjob now trusts the Gradle exit code for Kotlin/Native tests, preventing false-positive failures when K/N output formatting changes
Upgrade from 1.1.17
# gradle/libs.versions.toml
ghost = "1.1.18"