Tarmil / FSharp.SystemTextJson

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

Deserializtion doesn't match serialization (DU) (alternatively: can't deserialize DU case from bare string) #131

Open aggieben opened 1 year ago

aggieben commented 1 year ago

I'm working on an API client and modeling the API error codes like this:

[<JsonFSharpConverter(unionEncoding = (JsonUnionEncoding.Default ||| JsonUnionEncoding.UnwrapFieldlessTags))>]
type ApiErrorCode = 
    | [<JsonPropertyName "missing_scope">] MissingScope
    | [<JsonPropertyName "invalid_limit">] InvalidLimit
    // ...

Using these flags, serialization works the way I expect it to:

let testError = {| error = MissingScope |}
JsonSerializer.Serialize(testError)

This produces {"error": "missing_scope"}, just as I expect it to.

However, deserialization of a record like this doesn't work.

let jsonString = @"{ ""error"": ""missing_scope""}"
let json = JsonSerializer.Deserialize<JsonElement>(jsonString)
json.GetProperty("error").Deserialize<ApiErrorCode option>() // throws JsonException

The last line throws the following exception: JsonException: Failed to parse type blahblahblah: expected object, found String

Is there a way to deserialize a bare string into a DU case?

Tarmil commented 1 year ago

I pasted your code into fsi and it correctly returned Some MissingScope for the last line. What versions of .NET and FSharp.SystemTextJson are you using?

aggieben commented 1 year ago

I tested using LinqPad 7 with