Skip to content

Support serializing Stripe objects with ApiResource.GSON#2168

Merged
jar-stripe merged 2 commits intomasterfrom
jar/gson-bidirectional-serialization
Mar 4, 2026
Merged

Support serializing Stripe objects with ApiResource.GSON#2168
jar-stripe merged 2 commits intomasterfrom
jar/gson-bidirectional-serialization

Conversation

@jar-stripe
Copy link
Contributor

@jar-stripe jar-stripe commented Mar 4, 2026

Why?

Users serializing Stripe objects with ApiResource.GSON.toJson() get JSON output that ApiResource.GSON.fromJson() cannot deserialize back into the correct object. This happens because createGson() registers custom deserializers for several types but not corresponding serializers — so GSON falls back to default reflection, which produces a different JSON shape than the deserializers expect.

For example, an Invoice with an expanded customer field serializes the ExpandableField wrapper object ({"id":"cus_xxx","expanded_object":{...}}) instead of the flat customer object the deserializer expects. Similarly, polymorphic fields like Charge.source serialize as {} because the type adapter delegates to the interface type (which has no fields) rather than the concrete runtime type.

What?

  • Register the existing ExpandableFieldSerializer in createGson() — it was only registered in PRETTY_PRINT_GSON, so ApiResource.GSON fell back to reflection for serialization
  • Add StripeRawJsonObjectSerializer to write the raw JsonObject directly instead of wrapping it in {"json":{...}}
  • Fix write() in the three polymorphic TypeAdapterFactory classes (PaymentSourceTypeAdapterFactory, BalanceTransactionSourceTypeAdapterFactory, ExternalAccountTypeAdapterFactory) to resolve the adapter for the runtime type instead of the interface type, which produced {}
  • Add comprehensive tests that serialize objects with ApiResource.GSON.toJson() and verify they can be deserialized back with ApiResource.GSON.fromJson()

See Also

Changelog

  • ApiResource.GSON now supports serializing Stripe objects back into compatible JSON

ApiResource.GSON.toJson() produced JSON that could not be deserialized
back via ApiResource.GSON.fromJson() because createGson() registered
custom deserializers but not corresponding serializers for several types.

Three fixes:

1. Register the existing ExpandableFieldSerializer in createGson() —
   it was only used in PRETTY_PRINT_GSON, so expanded objects serialized
   as {"id":"x","expandedObject":{...}} instead of the flat resource.

2. Add StripeRawJsonObjectSerializer that writes the raw JsonObject
   directly, instead of the default reflection wrapping it in {"json":{}}.

3. Fix write() in the three polymorphic TypeAdapterFactories
   (PaymentSource, BalanceTransactionSource, ExternalAccount) to resolve
   the adapter for the runtime type via getDelegateAdapter, instead of
   delegating to the interface-typed adapter which produces {}.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude
@jar-stripe jar-stripe requested a review from a team as a code owner March 4, 2026 18:43
@jar-stripe jar-stripe requested review from prathmesh-stripe and removed request for a team March 4, 2026 18:43
@jar-stripe jar-stripe changed the title Fix bidirectional serialization in ApiResource.GSON Support serializing Stripe objects with ApiResource.GSON Mar 4, 2026
@jar-stripe jar-stripe closed this Mar 4, 2026
@jar-stripe jar-stripe reopened this Mar 4, 2026
@jar-stripe jar-stripe enabled auto-merge (squash) March 4, 2026 22:37
@jar-stripe jar-stripe merged commit 191492e into master Mar 4, 2026
15 checks passed
@jar-stripe jar-stripe deleted the jar/gson-bidirectional-serialization branch March 4, 2026 22:42
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.

2 participants