JSON Serialization Interview Questions
DATA › Networking
Is there ever still a good reason to reach for Moshi over kotlinx.serialization on a new Android feature today?
What a strong answer covers: kotlinx.serialization is now the default for new Kotlin and KMP code because it's compiler-plugin-driven, ships no reflection, and shares code cleanly across platforms, but Moshi can still make sense in a codebase that's heavily Retrofit-and-Java-interop centric, has existing custom JsonAdapters it doesn't want to rewrite, or needs Moshi-specific tooling. A weak answer just says 'always use kotlinx.serialization'; a strong one recognizes migration cost and existing investment are legitimate reasons to stay put, not just inertia.
How do you design your serialized models so an API that evolves over time, new enum values, renamed fields, a field going from optional to required, doesn't crash old versions of the app already out in the field?
What a strong answer covers: New enum values need a fallback branch (an UNKNOWN case with a custom serializer, or catching the SerializationException around decoding) rather than letting decode blow up on an unrecognized constant; fields should generally be added as nullable-with-default so old response shapes still decode; and ignoreUnknownKeys should be on by default so servers can add fields without breaking old clients. The trap is assuming the server team will always coordinate releases with the app team, when in practice the app is running old code against a newer API indefinitely.
Reflection-based serializers like Gson carry real production costs beyond 'it's less type-safe.' Walk me through what those costs actually look like at runtime and at build time, and why compile-time codegen avoids them.
What a strong answer covers: Reflection walks class metadata at runtime to find fields and constructors, which adds measurable per-object overhead and startup cost compared to a generated serializer calling known getters/constructors directly, and it also silently defeats R8/Proguard unless every serialized class is explicitly kept, which either bloats the keep rules or causes crashes in release builds that don't reproduce in debug. Compile-time codegen (kotlinx.serialization's plugin, Moshi's KSP) generates the (de)serialization code at build time, so there's no runtime reflection cost and no hidden Proguard keep-rule dependency.