Stringifying bigint to JSON using the following function:
let stringify (value: 'a) : string =
JS.JSON.stringify(value, (fun _ v ->
match v with
| :? string -> v
| :? System.Collections.IEnumerable ->
if JS.Array.isArray(v) then v
else JS.Array.from(v :?> JS.Iterable<obj>) |> box
| _ -> v
), 0)
for example, stringify 5I will return this:
{"signInt":1,"v":{"bound":1,"digits":[5]}}
instead of
"5"
Yes, for the fable-library types defined in JS/TS, we add toJson to the prototype, but we haven't done it yet for types defined in F#. I guess we should have a IJsonSerializable interface with a toJson method (lowercase) and make the types implement it so we are sure the member is attached to the prototype.
@alfonsogarciacaro I think I might have found a workaround but it is pretty ugly, testing for the existence of internal properties of the compiled BigInt, same for DateTimeOffset (workaround for #1710):
[<AutoOpen>]
module InteropUtil =
[<Emit("$1[$0]")>]
let get<'a> (key: string) (x: obj) : 'a = jsNative
[<Emit("$0 instanceof Date")>]
let isDate (x: obj) = jsNative
[<Emit("$0 in $1")>]
let hasKey (key: string) (x: 'a) = jsNative
let isDateOffset (x: obj) = isDate x && hasKey "offset" x
let isObjectLiteral (x: obj) = getTypeOf x = "object"
let isBigInt (x: obj) =
not (isNull x)
&& isObjectLiteral x
&& hasKey "signInt" x
&& hasKey "v" x
&& hasKey "digits" (get "v" x)
&& hasKey "bound" (get "v" x)
let stringify (value: 'a) : string =
JS.JSON.stringify(value, (fun key v ->
if isDateOffset (get key jsThis) then
let dateOffset : DateTimeOffset = get key jsThis
box (dateOffset.ToString("O"))
elif isBigInt (get key jsThis) then
let bigInt : bigint = get key jsThis
box (string (decimal bigInt))
else
match v with
| :? string -> v
| :? System.Collections.IEnumerable ->
if JS.Array.isArray(v) then v
else JS.Array.from(v :?> JS.Iterable<obj>) |> box
| _ when isBigInt v -> box (string (decimal (unbox<bigint> v)))
| _ when isDateOffset v -> box ((unbox<DateTimeOffset> v).ToString("O"))
| _ -> v
), 0)
Another little problem is that calling string or ToString() on bigint result in "[object Object]" (that's why I am converting to decimal first, probably needs a separate issue)
Hmm, actually converting the bigint to string should be the best way to serialize it to JSON. ToString with bigints is working fine in the REPL, either boxed or unboxed. I don't understand why you're getting "[object Object]" 馃槙
I might not had latest fable when I ran the tests, I will check :)
@Zaid-Ajaj Can this be closed?
I have fixed the problem by using reflection, so for me it is fixed in SimpleJson but if someone was to call JSON.stringify on big integers, they would get unexpected results. I think it is still a good idea to implement toJSON out of the box for these integers
Hopefully fixed by https://github.com/fable-compiler/Fable/commit/20a6d4555caceb9fa89718402c6d99d4787cc9ad. Will be released with 3.1.12, please reopen if it's still an issue.