JSON representation
The auto API gives you very limited control over the JSON representation. What it produces is described here.
Where the default doesn't fit, override the type with an extra coder, or write the coder yourself with the manual or codec API.
Primitives
Primitives are represented the same way as with the manual API. See Manual API - JSON representation - Numbers.
int64, uint64, decimal and bigint need an extra coder.
DateTime
A DateTime is represented as an ISO 8601 string, and decoded as UTC.
A value whose Kind is Local or Unspecified comes back as the same instant with Kind set to Utc, not as the value you encoded.
open System
open Thoth.Json.Core
open Thoth.Json.Core.Auto
open Thoth.Json.JavaScript
type Event =
{
At: DateTime
}
let encoder = Encode.Auto.generateEncoder<Event> ()
let decoder = Decode.Auto.generateDecoder<Event> ()
for kind in [ DateTimeKind.Utc; DateTimeKind.Local ] do
let json =
{
At = DateTime(2020, 1, 1, 12, 0, 0, kind)
}
|> encoder
|> Encode.toString 0
printfn "%A" kind
printfn "%s" json
Decode.fromString decoder json |> Docs.print
A DateTimeOffset keeps its offset.
Records
Records are represented as JSON objects, one property per field, named after the field and renamed by the case strategy.
open Thoth.Json.Core
open Thoth.Json.Core.Auto
open Thoth.Json.JavaScript
type User =
{
Name: string
Age: int
}
{
Name = "Geralt de Riv"
Age = 92
}
|> Encode.Auto.generateEncoder<User> ()
|> Encode.toString 4
|> printfn "%s"
Union case with no fields
A case without fields is represented as a string holding the case name.
open Thoth.Json.Core
open Thoth.Json.Core.Auto
open Thoth.Json.JavaScript
[<RequireQualifiedAccess>]
type Language =
| FSharp
| CSharp
Language.FSharp
|> Encode.Auto.generateEncoder<Language> ()
|> Encode.toString 0
|> printfn "%s"
Union case with fields
A case with fields is represented as a JSON array, holding the case name followed by one element per field.
open Thoth.Json.Core
open Thoth.Json.Core.Auto
open Thoth.Json.JavaScript
type MenuElement =
| Label of label: string
| ExternalLink of label: string * url: string
Label "Introduction"
|> Encode.Auto.generateEncoder<MenuElement> ()
|> Encode.toString 4
|> printfn "%s"
ExternalLink(label = "Fable", url = "http://fable.io")
|> Encode.Auto.generateEncoder<MenuElement> ()
|> Encode.toString 4
|> printfn "%s"
Option
By default the option type is erased:
Some 42is encoded as42Noneis encoded asnull, and left out of an object unlessskipNullFieldisfalse
Collections
Lists, arrays, sequences, sets and tuples are represented as JSON arrays.
open Thoth.Json.Core
open Thoth.Json.Core.Auto
open Thoth.Json.JavaScript
(1, "one", true)
|> Encode.Auto.generateEncoder<int * string * bool> ()
|> Encode.toString 0
|> printfn "%s"
set [ 1; 2; 3 ]
|> Encode.Auto.generateEncoder<Set<int>> ()
|> Encode.toString 0
|> printfn "%s"
Map
A Map<string, 'T> is represented as a JSON object.
Any other key type gives an array of [ key, value ] pairs.
open Thoth.Json.Core
open Thoth.Json.Core.Auto
open Thoth.Json.JavaScript
Map.ofList
[
"one", 1
"two", 2
]
|> Encode.Auto.generateEncoder<Map<string, int>> ()
|> Encode.toString 0
|> printfn "%s"
Map.ofList
[
1, "one"
2, "two"
]
|> Encode.Auto.generateEncoder<Map<int, string>> ()
|> Encode.toString 0
|> printfn "%s"
Enum
An enum is represented as the number it compiles to. Decoding rejects a number which isn't one of the declared values.
open Thoth.Json.Core
open Thoth.Json.Core.Auto
open Thoth.Json.JavaScript
type Rating =
| One = 1
| Two = 2
| Three = 3
Rating.Two
|> Encode.Auto.generateEncoder<Rating> ()
|> Encode.toString 0
|> printfn "%s"
"7" |> Decode.fromString (Decode.Auto.generateDecoder<Rating> ()) |> Docs.print
Class
Classes have to be added case by case through the extra argument.
Fable offers a limited reflection API, and classes are not part of it.