Skip to content

[Repo Assist] Fix JsonValue.Float serialization: append '.0' for whole-number floats#1606

Merged
dsyme merged 1 commit intomainfrom
repo-assist/fix-json-float-serialization-1356-923b690f238a89a3
Feb 22, 2026
Merged

[Repo Assist] Fix JsonValue.Float serialization: append '.0' for whole-number floats#1606
dsyme merged 1 commit intomainfrom
repo-assist/fix-json-float-serialization-1356-923b690f238a89a3

Conversation

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented Feb 22, 2026

🤖 Repo Assist here — I'm an automated AI assistant for this repository.

Closes #1356

Problem

JsonValue.Float(100.0).ToString() returns "100" instead of "100.0", discarding the fact that the value is a float. This violates downstream contracts that expect a JSON float.

JsonValue.Parse("100.0").ToString()  // ✓ "100.0"  (parse round-trips correctly)
JsonValue.Float(100.0).ToString()    // ✗ "100"    (should be "100.0")

Root Cause

JsonValue.WriteTo previously wrote Float values using w.Write(number), which calls (100.0 : float).ToString(). In .NET, (100.0).ToString() returns "100" — no decimal point — because IEEE 754 doubles carry no information about trailing zeros.

By contrast, JsonValue.Parse("100.0") stores the value as JsonValue.Number(Decimal.Parse("100.0")), and decimal preserves scale (trailing zeros), so it serialises as "100.0" correctly.

Fix

For the Float case, format using the "R" (round-trip) format specifier with InvariantCulture, then append ".0" if the result contains no decimal point and no exponent character — making the output unambiguously look like a JSON float:

-| Float number -> w.Write number
+| Float number ->
+    let s = number.ToString("R", CultureInfo.InvariantCulture)
+    w.Write s
+    if s.IndexOfAny([| '.'; 'E'; 'e' |]) = -1 then
+        w.Write ".0"

Examples after the fix:

Expression Before After
JsonValue.Float(100.0) "100" "100.0"
JsonValue.Float(100.5) "100.5" "100.5" (unchanged) ✓
JsonValue.Float(1e20) "1E+20" "1E+20" (unchanged) ✓
JsonValue.Float(nan) "null" "null" (unchanged) ✓

Test

Added three regression tests to JsonValue.fs covering the fixed case, fractional floats, and scientific notation.

Test Status

  • Build passes (dotnet build src/FSharp.Data.Json.Core/)
  • All 2841 tests in FSharp.Data.Core.Tests pass (2840 passed + 1 pre-existing failure: network test hitting www.google.com, blocked by build environment firewall — unrelated to this change)

Generated by Repo Assist

Generated by Repo Assist

To install this workflow, run gh aw add githubnext/agentics/workflows/repo-assist.md@b0296681ad309e6455276244363810b1e7d98335. View source at https://github.com/githubnext/agentics/tree/b0296681ad309e6455276244363810b1e7d98335/workflows/repo-assist.md.

Warning

⚠️ Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • www.google.com

JsonValue.Float(100.0).ToString() previously returned "100" instead of
"100.0", discarding the fact that the value is a float. This causes issues
when downstream consumers expect a JSON float (not an integer).

Root cause: the write path used w.Write(number) for the Float DU case which
calls number.ToString() — and (100.0).ToString() returns "100" in .NET.

Fix: format the float using the "R" round-trip format and, if the result
contains no decimal point or exponent character, append ".0". This matches
the behaviour of JsonValue.Parse("100.0") which correctly serialises as
"100.0" (because decimal 100M with Scale=1 already has the trailing zero).

Closes #1356

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review February 22, 2026 01:13
@dsyme dsyme closed this Feb 22, 2026
@dsyme dsyme reopened this Feb 22, 2026
@dsyme dsyme merged commit 0f4369c into main Feb 22, 2026
3 of 4 checks passed
@dsyme dsyme deleted the repo-assist/fix-json-float-serialization-1356-923b690f238a89a3 branch February 22, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FSharp.Data.Json serializes some floats as ints

1 participant