Regenerate with decimal_string enabled for v2 APIs#17
Conversation
V2 API fields with `format: decimal` now generate as `BigDecimal` instead of `String`. Driven by sdk-codegen#3369. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Committed-By-Agent: claude
The V2 API expects decimal fields as JSON strings (e.g., "25.5") not JSON numbers. Add a custom Gson TypeAdapter for BigDecimal to BODY_GSON that serializes via toPlainString(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Committed-By-Agent: claude
There was a problem hiding this comment.
⚠️ VibeOps Review — The PR has a critical bug in the BigDecimal TypeAdapter that will crash when the API returns numeric values instead of strings.
🟡 Human review required · verdict=request_changes
Blockers (1)
BigDecimal TypeAdapter crashes on numeric JSON tokens (confirmed by logic)
src/main/java/com/stripe/net/JsonEncoder.java:32
The read method calls in.nextString() unconditionally, but Gson's JsonReader.nextString() only works when the current token is a JSON string. If the Stripe API returns percent_ownership as a JSON number (e.g., 25.5) instead of a string (e.g., "25.5"), this will throw IllegalStateException because the current token is NUMBER, not STRING. The adapter assumes all BigDecimal values come as strings, but APIs can return them as either strings or numbers.
Check token type first:
```java
@Override
public BigDecimal read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.STRING) {
return new BigDecimal(in.nextString());
} else {
return BigDecimal.valueOf(in.nextDouble());
}
}
### What's good
- Good alignment between v1 and v2 APIs by standardizing on BigDecimal for decimal fields, improving type safety and consistency across the SDK.
### Context
- This PR removes a codegen workaround that was suppressing decimal_string mapping for v2 APIs, bringing them in line with v1 behavior.
---
*Reviewed by [VibeOps](https://vibeops.tech)*
| } | ||
|
|
||
| @Override | ||
| public BigDecimal read(JsonReader in) throws IOException { |
There was a problem hiding this comment.
🛑 Blocker · Bug · The read method calls in.nextString() unconditionally, but Gson's JsonReader.nextString() only works when the current token is a JSON string. If the Stripe API returns percent_ownership as a JSON number (e.g., 25.5) instead of a string (e.g., "25.5"), this will throw IllegalStateException because the current token is NUMBER, not STRING. The adapter assumes all BigDecimal values come as strings, but APIs can return them as either strings or numbers.
🔗 Backed by: agent reasoning
| public BigDecimal read(JsonReader in) throws IOException { | |
| Check token type first: | |
| ```java | |
| `Override` | |
| public BigDecimal read(JsonReader in) throws IOException { | |
| if (in.peek() == JsonToken.STRING) { | |
| return new BigDecimal(in.nextString()); | |
| } else { | |
| return BigDecimal.valueOf(in.nextDouble()); | |
| } | |
| } |
*Was this helpful? React with :+1: or :-1: to help VibeOps learn.*
| } | ||
|
|
||
| @Override | ||
| public BigDecimal read(JsonReader in) throws IOException { |
There was a problem hiding this comment.
Question — In JsonEncoder.java: The read method of BIG_DECIMAL_STRING_ADAPTER calls in.nextString() unconditionally. Could you clarify the intent here?
If this was intentional, I'll note it and won't flag it as a bug. If not, I can flag the related usages as blockers.
Reply here and I'll learn from your answer.
Why?
V2 API decimal fields (e.g.
amounton billing meter events) were previously generated as plainStringtypes, even though the same fields in v1 are generated asBigDecimal. A codegen workaround suppresseddecimal_stringtype mapping for all v2 APIs. That workaround has been removed.What?
decimal_stringenabled for v2 APIsBigDecimalinstead ofString, matching v1 behaviorTypeAdapter<BigDecimal>toJsonEncoder.BODY_GSONthat serializesBigDecimalas a JSON string (e.g.,"75.25"not75.25). The V2 API expects decimal fields as strings on the wire. V1 doesn't hit this becauseFormEncodercalls.toString()naturally.Testing
Integration tested against a live Stripe sandbox (6/6 tests passed):
BigDecimaldeserialization from Gson JSON string ✓BigDecimalnull when field absent ✓BigDecimalhigh precision (10 decimal places) ✓Amountconsolidation (sharedv2.Amountclass) ✓BigDecimalpercentOwnership ✓BigDecimalpercentOwnership ✓See Also
Changelog
StringtoBigDecimal. Code that reads or writes these fields asStringwill need to useBigDecimalinstead. Affected fields:percentOwnershipscoreAccountCreateParams,PersonCreateParams,AccountTokenCreateParams,PersonTokenCreateParams(all:percentOwnership)InvoiceItemCreateParams,InvoiceAddLinesParams,InvoiceUpdateLinesParams,InvoiceCreatePreviewParams(all:quantityDecimal)Mirrored from stripe/stripe-java#2187 by
jar-stripefor the VibeOps live demo. Real PR, real diff, reviewed by the same pipeline our customers run.