Skip to content

Commit fad41aa

Browse files
Fix JsonValue.Float serialization: append '.0' for whole-number floats
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>
1 parent 2566e81 commit fad41aa

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

src/FSharp.Data.Json.Core/JsonValue.fs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@ type JsonValue =
8686
| Boolean b -> w.Write(if b then "true" else "false")
8787
| Number number -> w.Write number
8888
| Float v when Double.IsInfinity v || Double.IsNaN v -> w.Write "null"
89-
| Float number -> w.Write number
89+
| Float number ->
90+
let s = number.ToString("R", CultureInfo.InvariantCulture)
91+
w.Write s
92+
// Ensure the output looks like a float (has a decimal point or exponent),
93+
// so that round-tripping through JSON preserves the Float type.
94+
if s.IndexOfAny([| '.'; 'E'; 'e' |]) = -1 then
95+
w.Write ".0"
9096
| String s ->
9197
w.Write "\""
9298
JsonValue.JsonStringEncodeTo w s

tests/FSharp.Data.Core.Tests/JsonValue.fs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,20 @@ let ``Serializes special float value as null`` v =
293293
let json = JsonValue.Float v
294294
json.ToString(JsonSaveOptions.DisableFormatting) |> should equal "null"
295295

296+
[<Test>]
297+
let ``Float value 100.0 serializes with decimal point`` () =
298+
// Regression test for https://github.com/fsprojects/FSharp.Data/issues/1356
299+
// JsonValue.Float(100.0) should serialize as "100.0", not "100"
300+
JsonValue.Float(100.0).ToString(JsonSaveOptions.DisableFormatting) |> should equal "100.0"
301+
302+
[<Test>]
303+
let ``Float value with fractional part serializes correctly`` () =
304+
JsonValue.Float(100.5).ToString(JsonSaveOptions.DisableFormatting) |> should equal "100.5"
305+
306+
[<Test>]
307+
let ``Float value in scientific notation serializes correctly`` () =
308+
JsonValue.Float(1e20).ToString(JsonSaveOptions.DisableFormatting) |> should equal "1E+20"
309+
296310
let normalize (str:string) =
297311
str.Replace("\r\n", "\n")
298312
.Replace("\r", "\n")

0 commit comments

Comments
 (0)