Skip to content

Add decimal_string coercion for v1 and v2 API fields#1769

Open
jar-stripe wants to merge 2 commits intomasterfrom
jar/decimal-tier2-python
Open

Add decimal_string coercion for v1 and v2 API fields#1769
jar-stripe wants to merge 2 commits intomasterfrom
jar/decimal-tier2-python

Conversation

@jar-stripe
Copy link
Contributor

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

Why?

The Stripe API uses decimal_string fields — high-precision decimal values that travel as JSON strings on the wire (e.g. "9.99") to avoid floating-point loss. This PR adds bidirectional coercion so these fields are transparent to SDK users: pass a Decimal in, get a Decimal back.

Coercion fires for both v1 and v2 resources. The codegen-emitted _field_encodings metadata drives which fields get coerced; resources without decimal fields are unaffected. This matches other SDK behavior (Java, Go, .NET).

What?

Runtime (hand-written):

  • stripe/_encode.py: Adds _coerce_decimal_string(value, *, encode) helper and handles "decimal_string" in _coerce_value (request path via _coerce_v2_params).
  • stripe/_stripe_object.py: Imports _coerce_decimal_string; adds "decimal_string" case to _coerce_field_value (response path via _field_encodings).
  • tests/test_decimal_string.py: 34 tests covering encode/decode, precision round-trips, nested objects, arrays, _coerce_v2_params integration, response coercion via _field_encodings, and v1 non-regression.

Generated:

  • All resources with decimal_string fields (v1 and v2) now emit _field_encodings = {"field_name": "decimal_string", ...}.
  • primitiveDecimalType changed from str to Decimal (stdlib decimal.Decimal), so response types and TypedDicts use Decimal | str instead of str.

See Also

Adds bidirectional coercion for decimal_string fields, following the
same pattern as int64_string:
- Encode: Decimal/int/float → str on request serialization
- Decode: str → decimal.Decimal on response hydration

_coerce_decimal_string added to _encode.py; decimal_string case added
to _coerce_value (request path) and _coerce_field_value (response path).
Precision is fully preserved through round-trips.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude
@jar-stripe jar-stripe requested a review from a team as a code owner March 20, 2026 23:08
@jar-stripe jar-stripe requested review from prathmesh-stripe and removed request for a team March 20, 2026 23:08
if isinstance(value, list):
return [
str(v)
if isinstance(v, (Decimal, int, float))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check is repeated twice. Seems like the list iteration should recurse into _coerce_decimal_string?

import time
from collections import OrderedDict
from decimal import Decimal
from typing import Any, Dict, Generator, Mapping, Optional, Tuple, Union

This comment was marked as spam.

…d v2 resources

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude
@jar-stripe jar-stripe changed the title Add decimal_string coercion for V2 API fields Add decimal_string coercion for v1 and v2 API fields Mar 21, 2026
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.

3 participants