An open API service indexing awesome lists of open source software.

https://github.com/angelmunoz/jdeck

A STJ Wraper library for JSON decoding for F# types
https://github.com/angelmunoz/jdeck

decoding dotnet fsharp json jsonserialization systemtextjson wrapper-library wrappper

Last synced: about 1 year ago
JSON representation

A STJ Wraper library for JSON decoding for F# types

Awesome Lists containing this project

README

          

# JDeck a System.Text.Json wrapper

JDeck is a [Thoth.Json]-like Json decoder based on `System.Text.Json` in a single file with no external
dependencies. Plays well with other libraries that use `System.Text.Json` like [FSharp.SystemTextJson]

> **Note:** While JDeck has no dependencies to start working right away, it is recommended to
> use [FsToolkit.ErrorHandling]

## Usage

For most F# types, you can use the `Decode.auto` function to decode JSON as shown below:

```fsharp
#r "nuget: JDeck, 1.0.0-beta-*"

open JDeck

type Person = {
name: string
age: int
emails: string list
}
let json = """{"name": "Alice", "age": 30, "emails": ["alice@name.com", "alice@age.com"] }"""

let result: Result = Decoding.auto(json)

match result with
| Ok person -> printfn $"Person: %A{person}"
| Error err -> printfn $"Error: %A{err}"
```

In cases where the data is inconclusive, you deserialize Discriminated Unions or does not play well with F# immutability, you can create a manual decoder.

```fsharp
#r "nuget: JDeck, 1.0.0-beta-*"

open System.Text.Json
open JDeck

type Person = {
Name: string
Age: int
Emails: string list
}
type ServerResponse = { Data: Person; Message: string }

let personDecoder: Decoder = fun person -> decode {
let! name = person |> Required.Property.get("name", Optional.string)
and! age = person |> Required.Property.get("age", Required.int)
and! emails = person |> Required.Property.list("emails", Optional.string)
return {
Name = name |> Option.defaultValue ""
Age = age
// Remove any optional value from the list
Emails = emails |> List.choose id
}
}
// Inconclusive data coming from the server
let person = """{"name": null, "age": 30, "emails": ["alice@name.com", "alice@age.com", null] }"""

let result: Result =
// ServerResponse will decode automatically while Person will use the custom decoder
Decoding.auto(
$$"""{ "data": {{person}}, "message": "Success" }""",
// Include your own decoder
JsonSerializerOptions(PropertyNameCaseInsensitive = true) |> Codec.useDecoder personDecoder
)

match result with
| Ok person -> printfn $"Person: %A{person}"
| Error err -> printfn $"Error: %A{err}"
```

## Acknowledgements

Nothing is done in the void, in this case I'd like to thank the following libraries for their inspiration and ideas:

- [Thoth.Json] for the inspiration and a cross-runtime solution to JSON decoding, compatible with F#, JS, and Python.
- [FsToolkit.ErrorHandling] for the general mechanism for dealing with Result types and Computation expressions

[Thoth.Json]: https://github.com/thoth-org/Thoth.Json
[FSharp.SystemTextJson]: https://github.com/Tarmil/FSharp.SystemTextJson
[FsToolkit.ErrorHandling]: https://github.com/demystifyfp/FsToolkit.ErrorHandling