Skip to content

feat: migrate from GSON to kotlinx.serialization - #1340

Closed
ibrahim-iqbal wants to merge 2 commits into
ReadYouApp:mainfrom
ibrahim-iqbal:feat/migrate-kotlinx-serialization
Closed

ibrahim-iqbal wants to merge 2 commits into
ReadYouApp:mainfrom
ibrahim-iqbal:feat/migrate-kotlinx-serialization

Conversation

@ibrahim-iqbal

Copy link
Copy Markdown

Summary

Migrates the entire codebase from GSON to kotlinx.serialization, addressing #994.

Changes

  • Retrofit: Swapped converter-gson for converter-kotlinx-serialization (Retrofit 2.11.0 built-in support) with Json { ignoreUnknownKeys = true }
  • DTOs: Added @Serializable and @SerialName annotations to all data classes (LatestRelease, AssetsItem, all GoogleReaderDTO.* classes, Diff)
  • SecurityKey hierarchy: Refactored decode() to use reified type parameters with @PublishedApi internal Json instance — keeps the abstract class approach (per maintainer feedback on feat: replace gson with kotlinx.serialization #997)
  • ProviderAPI / DiffMapHolder / DataStoreExt: Replaced Gson with Json and MapSerializer / JsonElement for generic map serialization
  • Version catalog: retrofit-gson → retrofit-kotlinx-serialization

Compatibility

  • All JSON field names preserved via @SerialName where Gson used @SerializedName
  • Existing encrypted SecurityKey data (DES + Base64) remains fully compatible — the JSON layer inside the encryption is format-identical
  • ignoreUnknownKeys = true ensures forward compatibility with API responses

Tests

Added SerializationCompatibilityTest that:

  • Deserializes hand-written JSON strings matching previous Gson output format
  • Verifies round-trip encode/decode for all SecurityKey types, GoogleReaderDTO classes, LatestRelease, and Diff
  • Tests Map<String, Diff> serialization compatibility (used by DiffMapHolder cache)

Tests bypass DESUtils (which depends on android.util.Base64) and test the JSON serialization layer directly.

Related

Test plan

  • Build compiles: ./gradlew compileFdroidDebugKotlin ✅
  • Unit tests pass: ./gradlew testFdroidDebugUnitTest --tests SerializationCompatibilityTest
  • Manual: verify app launches and can add/read RSS feeds
  • Manual: verify existing encrypted account credentials still decrypt correctly
  • Manual: verify GitHub release check still works (LatestRelease deserialization)

Replace Gson with kotlinx.serialization across the entire codebase:

- Swap retrofit-gson for retrofit-kotlinx-serialization in version catalog
- Replace GsonConverterFactory with Json.asConverterFactory in NetworkDataSource
- Add @serializable and @SerialName annotations to all DTO classes
  (LatestRelease, AssetsItem, GoogleReaderDTO.*, Diff)
- Migrate SecurityKey hierarchy to use reified inline decode<T>() with
  @PublishedApi internal Json instance (addresses PR ReadYouApp#997 review feedback
  about keeping abstract class, not sealed)
- Replace Gson in ProviderAPI, DiffMapHolder, and DataStoreExt with
  kotlinx.serialization equivalents using MapSerializer and JsonElement
- Add SerializationCompatibilityTest verifying JSON round-trip compatibility
  with previous Gson output format

Closes ReadYouApp#994
The hand-built MapSerializer used a serializer<String>() that does not
exist at the call site, so the unit-test source set failed to compile
and CI's test job never ran. Decoding the Map type directly checks the
same Gson-shaped JSON.
@ibrahim-iqbal
ibrahim-iqbal force-pushed the feat/migrate-kotlinx-serialization branch from 6b634b5 to 3107ba1 Compare November 4, 2026 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate to kotlinx.serialization

1 participant