Skip to content

Commit

Permalink
Expand documentation (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gastove authored Nov 6, 2021
1 parent cb8b5ed commit 6158ce1
Show file tree
Hide file tree
Showing 13 changed files with 229 additions and 33 deletions.
24 changes: 23 additions & 1 deletion .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
- name: Setup .NET Core 5
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.402
Expand All @@ -29,3 +29,25 @@ jobs:
run: dotnet run --no-build --project ./test/Tests.NewtonsoftJson/Tests.NewtonsoftJson.fsproj -c Release -f net5
- name: Test SystemTextJson
run: dotnet run --no-build --project ./test/Tests.SystemTextJson/Tests.SystemTextJson.fsproj -c Release -f net5

docs:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Setup .NET Core 5
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.402
- name: Restore dotnet tools
run: dotnet tool restore
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release
- name: Build Doc src
run: dotnet build -c Release ./docsrc/docs
- name: Render Docs
run: dotnet run --project ./docsrc/tool

1 change: 0 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<Version Condition=" '$(VersionSuffix)' == '' ">$(VersionPrefix)</Version>
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
<FileVersion>$(VersionPrefix).0</FileVersion>

</PropertyGroup>

<ItemGroup>
Expand Down
8 changes: 4 additions & 4 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ build_script:
- cmd: echo vs %VersionSuffix%"
- cmd: build.bat
test_script:
- cmd: dotnet run -p .\test\Tests.SystemJson\Tests.SystemJson.fsproj -c Release -f net461
- cmd: dotnet run -p .\test\Tests.FSharpData\Tests.FSharpData.fsproj -c Release -f net5
- cmd: dotnet run -p .\test\Tests.NewtonsoftJson\Tests.NewtonsoftJson.fsproj -c Release -f net5
- cmd: dotnet run -p .\test\Tests.SystemTextJson\Tests.SystemTextJson.fsproj -c Release -f net5
- cmd: dotnet run --project .\test\Tests.SystemJson\Tests.SystemJson.fsproj -c Release -f net461
- cmd: dotnet run --project .\test\Tests.FSharpData\Tests.FSharpData.fsproj -c Release -f net5
- cmd: dotnet run --project .\test\Tests.NewtonsoftJson\Tests.NewtonsoftJson.fsproj -c Release -f net5
- cmd: dotnet run --project .\test\Tests.SystemTextJson\Tests.SystemTextJson.fsproj -c Release -f net5

artifacts:
# pushing all *.nupkg files in build directory recursively
Expand Down
111 changes: 106 additions & 5 deletions docsrc/content/codec.fsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
(*** hide ***)
// This block of code is omitted in the generated HTML documentation. Use
// it to define helpers that you do not want to show in the documentation.
#r "nuget: FSharpPlus"
#r "nuget: System.Json"
#r "nuget: System.Json, 4.7.1"
#r "nuget: FSharpPlus, 1.2.2"
#r @"../../src/Fleece.SystemJson/bin/Release/netstandard2.1/Fleece.SystemJson.dll"

open Fleece.SystemJson
open Fleece.SystemJson.Operators


(**
## CODEC
For types that deserialize to Json Objets, typically (but not limited to) records, you can alternatively use codecs and have a single method which maps between fields and values.
```f#
#r "nuget: Fleece.SystemJson"
open Fleece.SystemJson
open Fleece.SystemJson.Operators
```
For types that deserialize to Json Objets, typically (but not limited to) records, you can alternatively use codecs and have a single method which maps between fields and values.
*)

type Person = {
Expand Down Expand Up @@ -60,6 +66,12 @@ type PersonF = {
|> jfieldWith jsonValueCodec "children" (fun x -> x.children)

(**
Both approaches build a codec from the same pieces:
- A constructor function that builds a new record from deserialized pieces
- A sequence of field specifications with `jfield/jfieldOpt` or `jreq/jot`.
These specs take a field name and a function for getting that fields value from a record instance.
Discriminated unions can be modeled with alternatives:
*)

Expand Down Expand Up @@ -92,7 +104,96 @@ type ShapeC =
(**
What's happening here is that we're getting a Codec to/from a Json Object (not neccesarily a JsonValue) which Fleece is able to take it and fill the gap by composing it with a codec from JsonObject to/from JsonValue.
We can also do that by hand, we can manipulate codecs by using functions in the Codec module. Here's an example:
For DUs that carry no data, a function is still necessary:
*)

type CompassDirection =
| North
| East
| South
| West
with
static member JsonObjCodec =
jchoice
[
(fun () -> North) <!> jreq "north" (function North -> Some () | _ -> None)
(fun () -> South) <!> jreq "south" (function South -> Some () | _ -> None)
(fun () -> East) <!> jreq "east" (function East -> Some () | _ -> None)
(fun () -> West) <!> jreq "west" (function West -> Some () | _ -> None)
]


(**
A common way to represent algebraic data types in JSON is to use a type tag.
For example:
**)

let someShapes = """
[
{
"type": "rectangle",
"width": 8.8,
"length": 12.0
},
{
"type": "circle",
"radius": 37.8
},
{
"type": "prism",
"width": [10.0, 23.0],
"height": 9.10
}
]
"""

open FSharpPlus
open FSharpPlus.Operators

type ShapeD =
| Rectangle of width : float * length : float
| Circle of radius : float
| Prism of width : float * float * height : float
with
static member JsonObjCodec =
/// Derives a concrete field codec for a required field and value
let inline jreqValue prop value codec =
let matchPropValue o =
match IReadOnlyDictionary.tryGetValue prop o with
| Some a when (ofJson a) = Ok value -> Ok o
| Some a -> Decode.Fail.invalidValue a value
| None -> Decode.Fail.propertyNotFound prop o
Codec.ofConcrete codec
|> Codec.compose (
matchPropValue,
fun encoded ->
if encoded.Count=0 then encoded // we have not encoded anything so no need to add property and value
else IReadOnlyDictionary.union (Dict.toIReadOnlyDictionary (dict [prop, toJson value])) encoded
)
|> Codec.toConcrete


jchoice
[
fun w l -> Rectangle (w,l)
<!> jreq "width" (function Rectangle(w, _) -> Some w | _ -> None)
<*> jreq "length" (function Rectangle(_, l) -> Some l | _ -> None)
|> jreqValue "type" "rectangle"

Circle
<!> jreq "radius" (function Circle (r) -> Some r | _ -> None)
|> jreqValue "type" "circle"

fun (w,w2) h -> Prism (w,w2,h)
<!> jreq "width" (function Prism (x, y, _) -> Some (x, y) | _ -> None)
<*> jreq "height" (function Prism (_, _, h) -> Some h | _ -> None)
|> jreqValue "type" "prism"
]

let parsedShapedD = parseJson<ShapeD list> someShapes

(**
We can manipulate codecs by using functions in the Codec module. Here's an example:
*)
open System.Text
let pf : PersonF= {name = ("John", "Doe"); age = None; children = [{name = ("Johnny", "Doe"); age = Some 21; children = []}]}
Expand Down
9 changes: 7 additions & 2 deletions docsrc/content/combinators.fsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
(*** hide ***)
// This block of code is omitted in the generated HTML documentation. Use
// it to define helpers that you do not want to show in the documentation.
#r "nuget: FSharpPlus"
#r "nuget: System.Json"
#r "nuget: System.Json, 4.7.1"
#r "nuget: FSharpPlus, 1.2.2"
#r @"../../src/Fleece.SystemJson/bin/Release/netstandard2.1/Fleece.SystemJson.dll"

open Fleece.SystemJson

(**
```f#
#r "nuget: Fleece.SystemJson"
open Fleece.SystemJson
```
## Combinators
So far we've seen how Fleece is capable of encoding/decoding by deriving automatically a codec from static members in the type.
Expand Down
13 changes: 9 additions & 4 deletions docsrc/content/comparison-with-json-net.fsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
(*** hide ***)
// This block of code is omitted in the generated HTML documentation. Use
// it to define helpers that you do not want to show in the documentation.
#r @"nuget: Newtonsoft.Json"
#r "nuget: FSharpPlus, 1.1.7"
#r @"../../src/Fleece.SystemJson/bin/Release/netstandard2.1/Fleece.SystemJson.dll"
#r "nuget: Newtonsoft.Json, 10.0.2"
#r "nuget: FSharpPlus, 1.2.2"
#r @"../../src/Fleece.NewtonsoftJson/bin/Release/netstandard2.1/Fleece.NewtonsoftJson.dll"

(**
```f#
#r "nuget: Fleece.NewtonsoftJson"
```
*)

open System
open Newtonsoft.Json
open FSharpPlus
Expand Down Expand Up @@ -55,7 +60,7 @@ with
static member OfJson (json:Linq.JToken) =
match json with
| JObject o ->
monad {
monad.strict {
match! o .@ "type" with
| "Bike" -> return Bike
| "Car" ->
Expand Down
65 changes: 65 additions & 0 deletions docsrc/content/further-techniques.fsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
(*** hide ***)
// This block of code is omitted in the generated HTML documentation. Use
// it to define helpers that you do not want to show in the documentation.
#r "nuget: System.Json, 4.7.1"
#r "nuget: FSharpPlus, 1.2.2"
#r @"../../src/Fleece.SystemJson/bin/Release/netstandard2.1/Fleece.SystemJson.dll"

open Fleece.SystemJson
open Fleece.SystemJson.Operators

(**
Sometimes, the JSON required by a given situation will contain fields that do not need to be present in the F# data model.
For example, the JSON-RPC 2.0 specification requires every request/response object to carry the field `jsonrpc` with value `"2.0"`.
In a codebase that only uses JSON-RPC 2.0, why capture this field on a record?
When writing `ToJson` and `OfJson` methods for this data, handling the required field is fairly natural:
*)

type Request =
{ Method: string
MethodParams: Map<string, string>}
static member ToJson (r: Request) =
jobj [
"method" .= r.Method
"params" .= r.MethodParams
"jsonrpc" .= "2.0"
]
static member OfJson json =
match json with
| JObject o ->
let method = o .@ "method"
let methodParams = o .@ "params"
// We require the "jsonrpc" field to be present
let jsonrpc = o .@ "jsonrpc"
match method, methodParams, jsonrpc with
| Decode.Success m, Decode.Success p, Decode.Success "2.0" -> // We enforce the value of the field
// ...but do not use it in the final object
Decode.Success {
Method = m
MethodParams = p
}
| x -> Error <| Uncategorized (sprintf "Error parsing person: %A" x)
| x -> Decode.Fail.objExpected x

(**
This can also be modeled with Codecs:
*)

type Response =
{ Result: string option
Error: string option }
static member JsonObjCodec =
fun r e _ -> { Result = r; Error = e }
|> withFields
|> jfieldOpt "result" (fun r -> r.Result)
|> jfieldOpt "error" (fun r -> r.Error)
|> jfield "jsonrpc" (fun _ -> "2.0")

(**
There are three parts to this.
First, the constructor is given an unused third parameter, which will receive the field required on the JSON object.
Second, the `"jsonrpc"` field is required using `jfield`; its getter always returns `"2.0"`
Finally: the fields must be in the correct order -- that is, the field specs must follow the order of the arguments in the constructor.
*)
7 changes: 3 additions & 4 deletions docsrc/content/giraffe.fsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
(*** hide ***)
// This block of code is omitted in the generated HTML documentation. Use
// it to define helpers that you do not want to show in the documentation.
#r "nuget: FSharpPlus"
#r "nuget: System.Json"
#r "nuget: TaskBuilder.fs,2.1.0"
#r "nuget: System.Json, 4.7.1"
#r "nuget: FSharpPlus, 1.2.2"
#r "nuget: TaskBuilder.fs, 2.1.0"
#r @"../../src/Fleece.SystemJson/bin/Release/netstandard2.1/Fleece.SystemJson.dll"

module Giraffe=
open System.Threading.Tasks
open System.IO
Expand Down
3 changes: 2 additions & 1 deletion docsrc/content/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Fleece
======

Fleece is a library intended to help with parsing and crafting specific Json without having to write data transfer objects in order to get the expected
Fleece is a library intended to help with parsing and crafting specific JSON without having to write data transfer objects in order to get the expected
representation.

### Introduction
Expand All @@ -11,6 +11,7 @@ You can get an overview of the important part of the library by reading the foll
- [ToJson and OfJson](./to-json-and-of-json.html) are the basic building blocks
- [Codec](./codec.html) let's you combine both ToJson and OfJson in one declaration
- [Combinators](./combinators.html) lets you have more control
- [Further Techniques](./further-techniques.html) describes ways of solving various JSON-wrangling problems

### Integration with Web frameworks

Expand Down
6 changes: 3 additions & 3 deletions docsrc/content/suave.fsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
(*** hide ***)
// This block of code is omitted in the generated HTML documentation. Use
// it to define helpers that you do not want to show in the documentation.
#r "nuget: FSharpPlus, 1.1.7"
#r "nuget: System.Json"
#r "nuget: Suave,2.5.6"
#r "nuget: System.Json, 4.7.1"
#r "nuget: FSharpPlus, 1.2.2"
#r "nuget: Suave, 2.5.6"
#r @"../../src/Fleece.SystemJson/bin/Release/netstandard2.1/Fleece.SystemJson.dll"

(**
Expand Down
6 changes: 3 additions & 3 deletions docsrc/content/to-json-and-of-json.fsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
(*** hide ***)
// This block of code is omitted in the generated HTML documentation. Use
// it to define helpers that you do not want to show in the documentation.
#r "nuget: FSharpPlus, 1.1.7"
#r "nuget: System.Json"
#r "nuget: System.Json, 4.7.1"
#r "nuget: FSharpPlus, 1.2.2"
#r @"../../src/Fleece.SystemJson/bin/Release/netstandard2.1/Fleece.SystemJson.dll"

open System.Json
open Fleece.SystemJson
open Fleece.SystemJson.Operators
#if FSHARPDATA
#r "nuget: FSharp.Data"
#r "nuget: FSharp.Data, 3.0.0"
#r @"../../src/Fleece.FSharpData/bin/Release/netstandard2.1/Fleece.FSharpData.dll"

open FSharp.Data
Expand Down
2 changes: 1 addition & 1 deletion docsrc/docs/docs.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>net5</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 6158ce1

Please sign in to comment.