Skip to content

BUG: Preserve full float precision when double_precision=15 in to_jso… #62083

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions pandas/io/json/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,46 @@
FrameSeriesStrT = TypeVar("FrameSeriesStrT", bound=Literal["frame", "series"])


# Helpers to stringify floats at full precision when requested
def _format_float_full_precision(value: Any) -> Any:
"""Return a string with full precision for finite floats; otherwise original.

Uses 17 significant digits to preserve IEEE-754 double precision.
"""
try:
# Fast path for Python float and NumPy floating scalars
if isinstance(value, (float, np.floating)):
x = float(value)
if np.isfinite(x):
return format(x, ".17g")
return value
except Exception:
# On any unexpected error, fall back to original value
return value
return value


def _stringify_floats_full_precision(obj: Any) -> Any:
"""Recursively convert finite floats to full-precision strings.

Leaves non-finite floats (NaN, +/-Inf) and non-float types unchanged.
Works for pandas Series/DataFrame, Python dict/list, and NumPy arrays.
"""
if isinstance(obj, Series):
return obj.map(_format_float_full_precision)
if isinstance(obj, DataFrame):
# Apply element-wise via Series.map to avoid deprecated/removed applymap
return obj.apply(lambda s: s.map(_format_float_full_precision))
if isinstance(obj, dict):
return {k: _stringify_floats_full_precision(v) for k, v in obj.items()}
if isinstance(obj, list):
return [_stringify_floats_full_precision(v) for v in obj]
if isinstance(obj, np.ndarray):
return [_stringify_floats_full_precision(v) for v in obj.tolist()]
# Scalars
return _format_float_full_precision(obj)


# interface to/from
@overload
def to_json(
Expand Down
Loading