fsprojects / FSharp.Json

F# JSON Reflection based serialization library
Apache License 2.0
222 stars 26 forks source link

Error thrown when given an int type where FSharp.Json expects a string #19

Closed oauo closed 5 years ago

oauo commented 5 years ago

If a type is set to an int and the given JSON gives a string an error is thrown rather than just converting the string to an int. This is particuarly useful when you have keys which are numbers but have to be represented as strings.

vsapronov commented 5 years ago

Hi Zoe! Could you please provide an example for this one? I need both F# record type and JSON sample. Thank you.

On Fri, Apr 19, 2019, 18:21 Zoë Shackleton notifications@github.com wrote:

If a type is set to an int and the given JSON gives a string an error is thrown rather than just converting the string to an int. This is particuarly useful when you have keys which are numbers but have to be represented as strings.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/vsapronov/FSharp.Json/issues/19, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGYLNTNANKBU3X2CZVC6I3PRJAVFANCNFSM4HHIHTIA .

oauo commented 5 years ago
let foo = "{\"0\":\"Foo\"}" |> Json.deserialize<Map<int,string>>

error

System.ArgumentException: 'Object of type 'System.String' cannot be converted to type 'System.Int32'.'
vsapronov commented 5 years ago

This behavior is intentional. FSharp.Json makes only obvious type conversions. For example: (F#) byte -> (JSON) number is obvious conversion. Other example would be: (F#) bool -> (JSON) bool.

You want FSharp.Json to make not obvious types conversion: (JSON) string -> (F#) int. Such conversion should be configured explicitly. You can try to achieve this with custom type transforms.

As a side note: JSON that uses integer as a object property name is not designed well. The Map<int,string> does not have any meaningful default representation in JSON. Most straight-forward guess is not valid JSON:

{1: "foo", 2: "bar"} //this is not valid JSON object - number can't be object property name

I would really consider changing format to something like:

[{"key": 1, "value": "foo"}, {"key": 2, "value": "bar"}]