vendredi 1 mars 2019

Fail to parse(?) decimals with FSharpValue.MakeRecord ONLY in iOS device with Region Spanish/Colombia

This bug not happened on Android, IOS emulator, osx, linux. Only on iOS device, when it have a region different to US/English.

I using reflection for decode Json values, and exactly in FSharpValue.MakeRecord the data of decimals get mangled.

Repro steps
  1. Create a Single View iOS app and fill it with:
namespace test
open System
open UIKit
open Foundation
open Microsoft.FSharp.Reflection

type DocumentRow = {
    doc_id:int32
    doc_kind:string
    doc_code:string
    customer_code:string
    from_code:string option
    username:string
    createdat:DateTime
    updatedat:DateTime
    dueat:DateTime option
    signature:string option
    authorized:string option
    delivery_order:int32
    price:decimal
    cost:decimal
    tax_value:decimal
    discount_value:decimal
    sub_total:decimal
    total:decimal
    status:string
    notes:string option
    syncdata:string option
    version:int32
}

module JSON =
    let fromJSON ty (fields:Reflection.PropertyInfo array) (objs:Map<string, obj>) =
        //printfn "%A" objs
        let values = fields |> Array.map(fun f ->
            let name = f.Name.ToLower()
            if objs.ContainsKey(name) then
                let value = objs.[name] 
                value
            else
                null
        )
        printfn "%A" values
        FSharpValue.MakeRecord(ty, values)

[<Register ("AppDelegate")>]
type AppDelegate () =
    inherit UIApplicationDelegate ()
    override val Window = null with get, set
    override this.FinishedLaunching (app, options) =
        let t = typedefof<DocumentRow>
        let fields = FSharpType.GetRecordFields t

        let data = [
            "doc_id", 1|> box
            "doc_kind", "O"|> box
            "doc_code", "ORD-3-1"|> box
            "customer_code", "70084254_32"|> box
            "from_code", null
            "username", "admin"|> box
            "createdat", DateTime.Now |> box
            "updatedat", DateTime.Now |> box
            "dueat", null
            "signature", null
            "authorized", null
            "delivery_order", 0|> box
            "price", 700M|> box
            "cost", 0M|> box
            "tax_value", 0M|> box
            "discount_value", 0M|> box
            "sub_total", 3500M|> box
            "total", 3500M|> box
            "status", "Draft"|> box
            "notes", null
            "syncdata", null
            "version", null
        ]
        let ob = Map.ofList data
        let r = JSON.fromJSON t fields ob :?> DocumentRow
        printfn "Result = %A" r
        true


  1. Run on emulator, it print in the output windows:
{doc_id = 1;
 doc_kind = "O";
 doc_code = "ORD-3-1";
 customer_code = "70084254_32";
 from_code = None;
 username = "admin";
 createdat = 28/02/2019 6:05:13 p. m.;
 updatedat = 28/02/2019 6:05:13 p. m.;
 dueat = None;
 signature = None;
 authorized = None;
 delivery_order = 0;
 price = 700M;
 cost = 0M;
 tax_value = 0M;
 discount_value = 0M;
 sub_total = 3500M;
 total = 3500M;
 status = "Draft";
 notes = None;
 syncdata = None;
 version = 0;}

this is correct.

  1. Run on a iOS device. I have use a iPhone 6 se, but is reproducible in many others.

It print:

{doc_id = 1;
 doc_kind = "O";
 doc_code = "ORD-3-1";
 customer_code = "70084254_32";
 from_code = None;
 username = "admin";
 createdat = 28/02/2019 6:04:12 p. m.;
 updatedat = 28/02/2019 6:04:12 p. m.;
 dueat = None;
 signature = None;
 authorized = None;
 delivery_order = 0;
 price = 12912720851596686131200M;
 cost = 0M;
 tax_value = 0M;
 discount_value = 0M;
 sub_total = 64563604257983430656000M;
 total = 64564290437145643974656M;
 status = "Draft";
 notes = None;
 syncdata = None;
 version = 0;}

See how all the decimal values get mangled.

Related information

iOS 12.1.4 Visual Studio Community 2017 for Mac Mono 5.16.0.221 (2018-06/b63e5378e38) (64-bit)

P.D: Reported in https://github.com/fsharp/fsharp/issues/893





Aucun commentaire:

Enregistrer un commentaire