Join our Newsletter — 33% off our NHI Course

What is the difference between using keep rules and using annotations for GSON serialization stability?

Keep rules preserve class and field names through the build pipeline, while annotations define which members should be serialized and what names they should use. In practice, annotations provide clearer intent for GSON models, and keep rules enforce that intent during obfuscation. Many teams use both to maintain stable JSON contracts.

How keep rules and annotations split responsibility

Keep rules and annotations solve different problems in a GSON pipeline. Annotations express serialization intent in the model itself: which fields participate, which names they should use, and which members are excluded. Keep rules protect those choices from build-time shrinking and obfuscation, so the JSON contract still matches what GSON expects at runtime.

That difference matters because GSON reads model metadata reflectively. If obfuscation renames a field that your JSON contract depends on, the payload can stop matching even though the source code still compiles. An annotation can tell GSON what to emit, but a keep rule tells the build tool not to rewrite the names or remove the members that GSON must see.

  • Use annotations when you want the model to declare its own JSON shape clearly.
  • Use keep rules when you need the build pipeline to preserve that shape after shrinking or obfuscation.
  • Use both when the serialized form must remain stable across releases and release builds are obfuscated.

For teams treating JSON as a stable API, the practical distinction is intent versus enforcement. Annotations document the contract in code, while keep rules make sure the contract survives packaging and optimization.

Where each approach fails if used alone

Annotations alone are usually enough in unminified builds, but they can fail once the app is obfuscated, because the JSON name seen by GSON may no longer match the runtime class or field name. Keep rules alone can preserve names, but they do not define which members should be exposed to serialization or what aliases they should carry, so the mapping intent becomes harder to read and maintain.

The usual failure mode is subtle: the code still runs, but the JSON changes in a way that breaks consumers, tests, or backward compatibility. That is why teams often pair explicit annotations with obfuscation rules for the same model classes. The annotation explains the contract, and the keep rule protects it from the build toolchain.

For GSON specifically, this distinction is most visible when a field name is part of the public payload. If you rely on reflection plus obfuscation without preserving those names, the contract can drift even when the source annotation remains correct.

A useful comparison point is the broader build and API stability mindset described in Ultimate Guide to NHIs, especially the operational cost of hidden contract drift and poor visibility. As a practical reference for serialization metadata and obfuscation behaviour, the OWASP API Security Top 10 reinforces why predictable payloads matter when data contracts are externally consumed.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

CIS Controls v8 provides the primary governance reference for this topic.

Framework Control / Reference Relevance
CIS Controls v8 CIS 8 — Account Management Serialization stability depends on preserving the model members that GSON reads at runtime.
CIS 16 — Application Software Security GSON contract stability is an application-security concern when build tools can alter runtime data shape.
CIS 18 — Application Penetration Testing Contract drift caused by obfuscation is best caught through runtime validation of serialized output.
Recommendation — Preserve the fields GSON depends on and verify build tooling does not rename or remove them. Test the compiled artifact to confirm the emitted JSON still matches the intended contract. Include serialized-output checks in validation to catch contract changes before release.

Practitioner Guidance

What to verify: Confirm whether the model is expected to survive shrinking, minification, or code obfuscation. If yes, test the compiled artifact, not just the source annotation, because source-level correctness does not guarantee runtime JSON stability.

Decision rule: If the field names themselves are part of the contract, keep the names with build rules and express the mapping with annotations. If the contract is internal and the build is not obfuscated, annotations may be sufficient, but you should still validate the emitted JSON in an integration test.

Common mistake: Treating annotations as if they also protect against obfuscation. They describe intent, but they do not stop a build tool from rewriting or removing members unless you explicitly preserve them.

Practitioner takeaway: For GSON stability, annotations define the schema, keep rules preserve it through the build pipeline, and the safest implementation is the one that proves the final JSON contract after obfuscation, not before.