From 3c90c9102bae47fab350046a75df2c2c5e865416 Mon Sep 17 00:00:00 2001 From: Repo Assist Date: Sun, 22 Feb 2026 03:53:27 +0000 Subject: [PATCH 1/2] Fix JsonConversions.AsDecimal to handle JsonValue.Float (closes #1230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the JSON parser encounters a number in exponential notation such as '3.45678E5', Decimal.TryParse with NumberStyles.Currency fails (because Currency does not include AllowExponent), so the value is stored as JsonValue.Float rather than JsonValue.Number. JsonConversions.AsDecimal previously only handled JsonValue.Number, so any field inferred as 'decimal' that received an exponential-notation value at runtime threw 'Expecting a Decimal … got …'. Fix: add a JsonValue.Float case to JsonConversions.AsDecimal that converts the float to decimal (mirroring the existing AsInteger / AsInteger64 patterns), guarding against Infinity/NaN and overflow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/FSharp.Data.Json.Core/JsonConversions.fs | 3 +++ tests/FSharp.Data.Tests/JsonProvider.fs | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/FSharp.Data.Json.Core/JsonConversions.fs b/src/FSharp.Data.Json.Core/JsonConversions.fs index 06dac6556..cc9a6fcf1 100644 --- a/src/FSharp.Data.Json.Core/JsonConversions.fs +++ b/src/FSharp.Data.Json.Core/JsonConversions.fs @@ -47,6 +47,9 @@ type JsonConversions = static member AsDecimal cultureInfo = function | JsonValue.Number n -> Some n + | JsonValue.Float f when not (Double.IsInfinity f) && not (Double.IsNaN f) -> + try Some(decimal f) + with :? OverflowException -> None | JsonValue.String s -> TextConversions.AsDecimal cultureInfo s | _ -> None diff --git a/tests/FSharp.Data.Tests/JsonProvider.fs b/tests/FSharp.Data.Tests/JsonProvider.fs index 20a891010..af153ea0e 100644 --- a/tests/FSharp.Data.Tests/JsonProvider.fs +++ b/tests/FSharp.Data.Tests/JsonProvider.fs @@ -816,6 +816,18 @@ let ``ParseList return result list`` () = let prov = NumericFields.ParseList(""" [{"a":123}, {"a":987}] """) prov |> Array.map (fun v -> v.A) |> Array.sort |> should equal [|123M; 987M|] +// Regression test for https://github.com/fsprojects/FSharp.Data/issues/1230 +// When a JSON array sample mixes decimal and exponential-notation numbers, the inferred +// type is decimal (because the exponential value is stored as JsonValue.Float and inferred +// as integer, which is then unified with decimal). At runtime, any exponential-notation +// number in the actual JSON must also be convertible to decimal. +type ExponentialDecimalProvider = JsonProvider<"""{"mydata": [1, 2.34567E5, 3.14]}"""> + +[] +let ``Decimal inferred from mixed-notation array can parse exponential notation at runtime`` () = + let result = ExponentialDecimalProvider.Parse("""{"mydata": [2, 3.45678E5, 9.01]}""") + result.Mydata |> should equal [| 2M; 345678M; 9.01M |] + type ServiceResponse = JsonProvider<"""[ { "code": 0, "value": {"generic payload": "yes"}, "message": null}, From 3f1bd286d5099cd545cd59002747a0767f47b71e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Feb 2026 09:31:29 +0000 Subject: [PATCH 2/2] Fix formatting: expand try/with in AsDecimal to satisfy fantomas Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/FSharp.Data.Json.Core/JsonConversions.fs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/FSharp.Data.Json.Core/JsonConversions.fs b/src/FSharp.Data.Json.Core/JsonConversions.fs index cc9a6fcf1..93e3f08dc 100644 --- a/src/FSharp.Data.Json.Core/JsonConversions.fs +++ b/src/FSharp.Data.Json.Core/JsonConversions.fs @@ -48,8 +48,10 @@ type JsonConversions = function | JsonValue.Number n -> Some n | JsonValue.Float f when not (Double.IsInfinity f) && not (Double.IsNaN f) -> - try Some(decimal f) - with :? OverflowException -> None + try + Some(decimal f) + with :? OverflowException -> + None | JsonValue.String s -> TextConversions.AsDecimal cultureInfo s | _ -> None