Tarmil / FSharp.SystemTextJson

System.Text.Json extensions for F# types
MIT License
325 stars 44 forks source link

Doesn't work when output type is WinExe #88

Open LiteracyFanatic opened 3 years ago

LiteracyFanatic commented 3 years ago

I'm using this from an Avalonia program and it works great as long as the OutputType is set to Exe. However, on Windows I have to set OutputType to WinExe or a console window will spawn alongside my GUI. Unfortunately, WinExe seems to break deserializing JSON with this library. I get an exception saying that F# lists aren't supported.

Tarmil commented 3 years ago

That's odd, at first glance I don't see why changing the OutputType should change anything regarding System.Text.Json. I'll try to see if I can reproduce.

LiteracyFanatic commented 3 years ago

Yeah, I can't imagine why they should be related, but the only difference between the working and failing versions are whether I publish with \p:OutputType=Exe or \p:OutputType=WinExe.

I can't share the whole project since it was for a client, but the relevant parts look like this. The domain logic and parsing is in a library. Then loadStock gets dispatched by a Cmd and returns a Msg with the data when finished in the UI project.

type StockHistoryItem = {
    Date: DateTime
    Close: double option
}

type StockHistory = {
    Ticker: string
    Data: StockHistoryItem list
}

type StockError =
    | ApiError of ticker: string * ex: Exception
    | NotEnoughData of StockHistory
    | MissingData of StockHistory
    | LoadingError of file: string * ex: Exception

let jsonSerializationOptions = JsonSerializerOptions()
jsonSerializationOptions.PropertyNameCaseInsensitive <- true
jsonSerializationOptions.WriteIndented <- true
jsonSerializationOptions.Converters.Add(JsonFSharpConverter())

let loadStock (file: string): Task<Result<StockHistory, StockError>> =
    task {
        try
            let json = File.OpenRead(file)
            let! stock = JsonSerializer.DeserializeAsync<StockHistory>(json, jsonSerializationOptions).ConfigureAwait(false)
            return Ok { stock with Data = List.sortByDescending (fun s -> s.Date) stock.Data }
        with
        | e ->
            return Error (LoadingError (file, e))
    }
let loadStocks () =
    task {
        let! stocks =
            Directory.EnumerateFiles(stocksDir, "*.json")
            |> Seq.map Stocks.loadStock
            |> Task.WhenAll
        return FinishLoadStocks (List.ofArray stocks)
    }