F# JsonProvider type fails to parse decimal

127 Views Asked by At

Why can't someJsonType parse 9.433536880271462E-4 to decimal?

Parsing the value myself works fine let c = decimal "9.433536880271462E-4"

#r "nuget: FSharp.Data, 3.3.3"
type someJsonType = FSharp.Data.JsonProvider<"""
{
  "point": 45.5
}
""">
let a = someJsonType.Parse "{ \"point\": 12.5 }"
let b = someJsonType.Parse "{ \"point\": 9.433536880271462E-4 }"
let c = someJsonType.Parse "{ \"point\": 0.0009433536880271462 }"
printfn "%f" a.Point // OK
printfn "%f" b.Point // exception
printfn "%f" c.Point // OK
let d = decimal "9.433536880271462E-4" // OK

Exception:

System.Exception: Expecting a Decimal at '/point', got 0.0009433536880271462
   at Microsoft.FSharp.Core.PrintfModule.PrintFormatToStringThenFail@1433.Invoke(String message) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\printf.fs:line 1433
   at System.Runtime.CompilerServices.RuntimeHelpers.DispatchTailCalls(IntPtr callersRetAddrSlot, IntPtr callTarget, IntPtr retVal)
   at [email protected](T2 u, T3 v) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\prim-types.fs:line 3298
   at <StartupCode$FSI_0072>.$FSI_0072.main@()
Stopped due to error
1

There are 1 best solutions below

2
Martin Freedman On

The data type is inferred as decimal, but b is float hence the exception. This is a quirk that means you have to modify the sample json to ensure the correct type is inferred. So, if you want to infer float then you have to modify your sample:

#r "nuget: FSharp.Data, 3.3.3"
type someJsonType = FSharp.Data.JsonProvider<"""
{
  "point": 9.433536880271462E-4
}
""">
let a = someJsonType.Parse "{ \"point\": 12.5 }"
let b = someJsonType.Parse "{ \"point\": 9.433536880271462E-4 }"
let c = someJsonType.Parse "{ \"point\": 0.0009433536880271462 }"
printfn "%f" a.Point // val a.Point is float with get
printfn "%f" b.Point // OK
printfn "%f" c.Point // OK

If you want it to be decimal you can cast this after loading json data into your local object. This is what you are actually doing with let d = decimal "9.433536880271462E-4" // OK

(Similarly if the json schema is meant to be providing floats or decimals but the sample only has what appears to be an int, an int would be inferred, so again you have to modify the sample to ensure the correct type is inferred)

The JsonProvider can only work with what is at hand in the sample json, hence the importance of the sample helping the inference.

(Note: We don't always have control of the sample json, if coming from a live third party site, so I think some form of type annotation might be useful to assist but as far as I know this does not exist yet.)

Related Questions in F#

Related Questions in F#-DATA