Fleece


CODEC

#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 = {
    name : string * string
    age : int option
    children: Person list }
    with
    static member JsonObjCodec =
        fun f l a c -> { name = (f, l); age = a; children = c }
        <!> jreq  "firstName" (Some << fun x -> fst x.name)
        <*> jreq  "lastName"  (Some << fun x -> snd x.name)
        <*> jopt  "age"       (fun x -> x.age) // Optional fields: use 'jopt'
        <*> jreq  "children"  (fun x -> Some x.children)


let p = {name = ("John", "Doe"); age = None; children = [{name = ("Johnny", "Doe"); age = Some 21; children = []}]}
//printfn "%s" (string (toJson p))

let john = parseJson<Person> """{
    "children": [{
        "children": [],
        "age": 21,
        "lastName": "Doe",
        "firstName": "Johnny"
    }],
    "lastName": "Doe",
    "firstName": "John"
}"""

If you prefer you can write the same with functions:

type PersonF = {
    name : string * string
    age : int option
    children: PersonF list }
    with
    static member JsonObjCodec =
        fun f l a c -> { name = (f, l); age = a; children = c }
        |> withFields
        |> jfield    "firstName" (fun x -> fst x.name)
        |> jfield    "lastName"  (fun x -> snd x.name)
        |> jfieldOpt "age"       (fun x -> x.age)
        |> jfieldWith jsonValueCodec "children"  (fun x -> x.children)

Both approaches build a codec from the same pieces:

Discriminated unions can be modeled with alternatives:

type Shape =
    | Rectangle of width : float * length : float
    | Circle of radius : float
    | Prism of width : float * float * height : float
    with
        static member JsonObjCodec =
            Rectangle <!> jreq "rectangle" (function Rectangle (x, y) -> Some (x, y) | _ -> None)
            <|> ( Circle <!> jreq "radius" (function Circle x -> Some x | _ -> None) )
            <|> ( Prism <!> jreq "prism"   (function Prism (x, y, z) -> Some (x, y, z) | _ -> None) )

or using the jchoice combinator:

type ShapeC =
    | Rectangle of width : float * length : float
    | Circle of radius : float
    | Prism of width : float * float * height : float
    with
        static member JsonObjCodec =
            jchoice
                [
                    Rectangle <!> jreq "rectangle" (function Rectangle (x, y) -> Some (x, y) | _ -> None)
                    Circle    <!> jreq "radius"    (function Circle x -> Some x | _ -> None)
                    Prism     <!> jreq "prism"     (function Prism (x, y, z) -> Some (x, y, z) | _ -> None)
                ]

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.

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 = []}]}

let personBytesCodec =
    let getString (bytes:byte array) = Encoding.UTF8.GetString bytes
    PersonF.JsonObjCodec
    |> Codec.compose jsonObjToValueCodec    // this is the codec that fills the gap to/from JsonValue
    |> Codec.compose jsonValueToTextCodec   // this is a codec between JsonValue and JsonText
    |> Codec.invmap getString Encoding.UTF8.GetBytes    // This is a pair of of isomorphic functions

let bytePerson = Codec.encode personBytesCodec pf
// val bytePerson : byte [] = [|123uy; 13uy; 10uy; 32uy; 32uy; ... |]
let p' = Codec.decode personBytesCodec bytePerson

While if the type of codec is concrete then we need to convert it to before composing it

let personBytesCodec2 =
    let getString (bytes:byte array) = Encoding.UTF8.GetString bytes
    Person.JsonObjCodec
    |> Codec.ofConcrete
    |> Codec.compose jsonObjToValueCodec    // this is the codec that fills the gap to/from JsonValue
    |> Codec.compose jsonValueToTextCodec   // this is a codec between JsonValue and JsonText
    |> Codec.invmap getString Encoding.UTF8.GetBytes    // This is a pair of of isomorphic functions
namespace Fleece
module SystemJson from Fleece
module Operators from Fleece.SystemJson
Person.name: string * string
Multiple items
val string : value:'T -> string
<summary>Converts the argument to a string using <c>ToString</c>.</summary>
<remarks>For standard integer and floating point values the and any type that implements <c>IFormattable</c><c>ToString</c> conversion uses <c>CultureInfo.InvariantCulture</c>. </remarks>
<param name="value">The input value.</param>
<returns>The converted string.</returns>


--------------------
type string = System.String
<summary>An abbreviation for the CLI type <see cref="T:System.String" />.</summary>
<category>Basic Types</category>
Person.age: int option
Multiple items
val int : value:'T -> int (requires member op_Explicit)
<summary>Converts the argument to signed 32-bit integer. This is a direct conversion for all primitive numeric types. For strings, the input is converted using <c>Int32.Parse()</c> with InvariantCulture settings. Otherwise the operation requires an appropriate static conversion method on the input type.</summary>
<param name="value">The input value.</param>
<returns>The converted int</returns>


--------------------
[<Struct>] type int = int32
<summary>An abbreviation for the CLI type <see cref="T:System.Int32" />.</summary>
<category>Basic Types</category>


--------------------
type int<'Measure> = int
<summary>The type of 32-bit signed integer numbers, annotated with a unit of measure. The unit of measure is erased in compiled code and when values of this type are analyzed using reflection. The type is representationally equivalent to <see cref="T:System.Int32" />.</summary>
<category>Basic Types with Units of Measure</category>
type 'T option = Option<'T>
<summary>The type of optional values. When used from other CLI languages the empty option is the <c>null</c> value. </summary>
<remarks>Use the constructors <c>Some</c> and <c>None</c> to create values of this type. Use the values in the <c>Option</c> module to manipulate values of this type, or pattern match against the values directly. 'None' values will appear as the value <c>null</c> to other CLI languages. Instance methods on this type will appear as static methods to other CLI languages due to the use of <c>null</c> as a value representation.</remarks>
<category index="3">Options</category>
Person.children: Person list
type Person = { name: string * string age: int option children: Person list } static member JsonObjCodec : ConcreteCodec<KeyValuePair<string,JsonValue> list,KeyValuePair<string,JsonValue> list,Person,Person>
type 'T list = List<'T>
<summary>The type of immutable singly-linked lists. </summary>
<remarks>See the <see cref="T:Microsoft.FSharp.Collections.ListModule" /> module for further operations related to lists. Use the constructors <c>[]</c> and <c>::</c> (infix) to create values of this type, or the notation <c>[1; 2; 3]</c>. Use the values in the <c>List</c> module to manipulate values of this type, or pattern match against the values directly. See also <a href="https://docs.microsoft.com/dotnet/fsharp/language-reference/lists">F# Language Guide - Lists</a>. </remarks>
val f : string
val l : string
val a : int option
val c : Person list
val jreq : name:string -> getter:('T -> 'param option) -> ConcreteCodec<System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,'param,'T> (requires member OfJson and member ToJson)
<summary> Derives a concrete field codec for a required field </summary>
union case Option.Some: Value: 'T -> Option<'T>
<summary>The representation of "Value of type 'T"</summary>
<param name="Value">The input value.</param>
<returns>An option representing the value.</returns>
val x : Person
val fst : tuple:('T1 * 'T2) -> 'T1
<summary>Return the first element of a tuple, <c>fst (a,b) = a</c>.</summary>
<param name="tuple">The input tuple.</param>
<returns>The first value.</returns>
val snd : tuple:('T1 * 'T2) -> 'T2
<summary>Return the second element of a tuple, <c>snd (a,b) = b</c>.</summary>
<param name="tuple">The input tuple.</param>
<returns>The second value.</returns>
val jopt : prop:string -> getter:('a -> 'b option) -> ConcreteCodec<System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,'b option,'a> (requires member OfJson and member ToJson)
<summary> Derives a concrete field codec for an optional field </summary>
val p : Person
union case Option.None: Option<'T>
<summary>The representation of "No value"</summary>
val john : Person ParseResult
val parseJson : x:string -> 'a ParseResult (requires member OfJson)
<summary> Parses a Json Text and maps to a type </summary>
PersonF.name: string * string
PersonF.age: int option
PersonF.children: PersonF list
type PersonF = { name: string * string age: int option children: PersonF list } static member JsonObjCodec : (IReadOnlyDictionary<string,JsonValue> -> Result<PersonF,DecodeError>) * (PersonF -> IReadOnlyDictionary<string,JsonValue>)
val c : PersonF list
val withFields : f:'a -> ('b -> Result<'a,'c>) * ('d -> System.Collections.Generic.IReadOnlyDictionary<'e,'f>) (requires equality)
<summary>Initialize the field mappings.</summary>
<param name="f">An object constructor as a curried function.</param>
<returns>The resulting object codec.</returns>
val jfield : fieldName:string -> getter:('T -> 'Value) -> Decoder<System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,('Value -> 'Rest)> * Encoder<System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,'T> -> (System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue> -> Result<'Rest,DecodeError>) * ('T -> System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>) (requires member OfJson and member ToJson)
<summary>Appends a field mapping to the codec.</summary>
<param name="fieldName">A string that will be used as key to the field.</param>
<param name="getter">The field getter function.</param>
<param name="rest">The other mappings.</param>
<returns>The resulting object codec.</returns>
val x : PersonF
val jfieldOpt : fieldName:string -> getter:('T -> 'Value option) -> Decoder<System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,('Value option -> 'Rest)> * Encoder<System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,'T> -> (System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue> -> Result<'Rest,DecodeError>) * ('T -> System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>) (requires member ToJson and member OfJson)
<summary>Appends an optional field mapping to the codec.</summary>
<param name="fieldName">A string that will be used as key to the field.</param>
<param name="getter">The field getter function.</param>
<param name="rest">The other mappings.</param>
<returns>The resulting object codec.</returns>
val jfieldWith : (System.Json.JsonValue -> Result<'a,DecodeError>) * ('Value -> System.Json.JsonValue) -> fieldName:string -> getter:('T -> 'Value) -> Decoder<System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,('a -> 'Rest)> * Encoder<System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,'T> -> (System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue> -> Result<'Rest,DecodeError>) * ('T -> System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>)
<summary>Appends a field mapping to the codec.</summary>
<param name="codec">The codec to be used.</param>
<param name="fieldName">A string that will be used as key to the field.</param>
<param name="getter">The field getter function.</param>
<param name="rest">The other mappings.</param>
<returns>The resulting object codec.</returns>
val jsonValueCodec<'t (requires member OfJson and member ToJson)> : Codec<System.Json.JsonValue,'t> (requires member OfJson and member ToJson)
<summary> Derive automatically a JsonCodec, based of OfJson and ToJson static members </summary>
union case Shape.Rectangle: width: float * length: float -> Shape
Multiple items
val float : value:'T -> float (requires member op_Explicit)
<summary>Converts the argument to 64-bit float. This is a direct conversion for all primitive numeric types. For strings, the input is converted using <c>Double.Parse()</c> with InvariantCulture settings. Otherwise the operation requires an appropriate static conversion method on the input type.</summary>
<param name="value">The input value.</param>
<returns>The converted float</returns>


--------------------
[<Struct>] type float = System.Double
<summary>An abbreviation for the CLI type <see cref="T:System.Double" />.</summary>
<category>Basic Types</category>


--------------------
type float<'Measure> = float
<summary>The type of double-precision floating point numbers, annotated with a unit of measure. The unit of measure is erased in compiled code and when values of this type are analyzed using reflection. The type is representationally equivalent to <see cref="T:System.Double" />.</summary>
<category index="6">Basic Types with Units of Measure</category>
union case Shape.Circle: radius: float -> Shape
union case Shape.Prism: width: float * float * height: float -> Shape
val x : float
val y : float
val z : float
union case ShapeC.Rectangle: width: float * length: float -> ShapeC
union case ShapeC.Circle: radius: float -> ShapeC
union case ShapeC.Prism: width: float * float * height: float -> ShapeC
val jchoice : codecs:seq<ConcreteCodec<'S,'S,'t1,'t2>> -> ConcreteCodec<'S,'S,'t1,'t2> (requires member ( + ))
union case CompassDirection.North: CompassDirection
union case CompassDirection.East: CompassDirection
union case CompassDirection.South: CompassDirection
union case CompassDirection.West: CompassDirection
val someShapes : string
namespace FSharpPlus
module Operators from FSharpPlus
<summary> Generic functions and operators </summary>
union case ShapeD.Rectangle: width: float * length: float -> ShapeD
val length : source:'Foldable<'T> -> int (requires member Length)
<summary>Gets the number of elements in the foldable.</summary>
<category index="11">Foldable</category>
<param name="source">The input foldable.</param>
<returns>The length of the foldable.</returns>
union case ShapeD.Circle: radius: float -> ShapeD
union case ShapeD.Prism: width: float * float * height: float -> ShapeD
val jreqValue : (string -> string -> ConcreteCodec<System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,'a,'b> -> ConcreteCodec<System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,'a,'b>)
 Derives a concrete field codec for a required field and value
val prop : string
val value : string
val codec : ConcreteCodec<System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,'a,'b>
val matchPropValue : ('c -> Result<'c,DecodeError>) (requires 'c :> System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>)
val o : #System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>
module IReadOnlyDictionary from FSharpPlus
<summary> Additional operations on IReadOnlyDictionary&lt;'Key, 'Value&gt; </summary>
val tryGetValue : k:'Key -> dct:System.Collections.Generic.IReadOnlyDictionary<'Key,'Value> -> 'Value option
<summary>Tries to get the value of the given key.</summary>
<remarks>This is a function wrapper for the IReadOnlyDictionary.TryGetValue method, representing the result as an Option&lt;value&gt; instead of a bool plus an out-value. </remarks>
<param name="k">The key whose value you wish to find.</param>
<param name="dct">The input IReadOnlyDictionary.</param>
<returns>An option wrapped value.</returns>
val a : System.Json.JsonValue
val ofJson : x:System.Json.JsonValue -> 't ParseResult (requires member OfJson)
<summary> Maps Json to a type </summary>
union case Result.Ok: ResultValue: 'T -> Result<'T,'TError>
<summary> Represents an OK or a Successful result. The code succeeded with a value of 'T. </summary>
module Decode from Fleece.SystemJson
module Fail from Fleece.SystemJson.Decode
val invalidValue : v:System.Json.JsonValue -> o:string -> Result<'t,DecodeError>
val propertyNotFound : p:string -> o:System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue> -> Result<'d,DecodeError>
Multiple items
module Codec from Fleece.SystemJson
<summary> Functions operating on Codecs (as pair of functions) </summary>

--------------------
type Codec<'S,'t> = Codec<'S,'S,'t>
<summary> A codec for raw type 'S to strong type 't. </summary>

--------------------
type Codec<'S1,'S2,'t> = Codec<'S1,'S2,'t,'t>
<summary> A decoder from raw type 'S1 and encoder to raw type 'S2 for type 't. </summary>

--------------------
type Codec<'S1,'S2,'t1,'t2> = Decoder<'S1,'t1> * Encoder<'S2,'t2>
<summary> A decoder from raw type 'S1 and encoder to raw type 'S2 for string types 't1 and 't2. </summary>
val ofConcrete : ConcreteCodec<'c list,System.Collections.Generic.KeyValuePair<'d,'e> list,'f,'g> -> ('h -> 'f ParseResult) * ('g -> System.Collections.Generic.IReadOnlyDictionary<'d,'e>) (requires equality and member ToList)
<summary> Extracts a pair of functions from a ConcreteCodec </summary>
val compose : ('c -> 'd) * ('g -> 'h) -> ('f -> 'e) * ('i -> 'g) -> ('c -> 'e) * ('i -> 'h) (requires member ( >>= ))
<summary> Creates a new codec which is the result of applying codec2 then codec1 for encoding and codec1 then codec2 for decoding </summary>
val encoded : System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>
property System.Collections.Generic.IReadOnlyCollection.Count: int with get
<summary>Gets the number of elements in the collection.</summary>
<returns>The number of elements in the collection.</returns>
val union : source:System.Collections.Generic.IReadOnlyDictionary<'Key,'T> -> altSource:System.Collections.Generic.IReadOnlyDictionary<'Key,'T> -> System.Collections.Generic.IReadOnlyDictionary<'Key,'T> (requires equality)
<summary> Returns the union of two read-only dictionaries, preferring values from the first in case of duplicate keys. </summary>
module Dict from FSharpPlus
<summary> Additional operations on IDictionary&lt;'Key, 'Value&gt; </summary>
val toIReadOnlyDictionary : source:System.Collections.Generic.IDictionary<'c,'d> -> System.Collections.Generic.IReadOnlyDictionary<'c,'d>
<summary> Converts an IDictionary to an IReadOnlyDictionary. </summary>
val dict : keyValuePairs:seq<'Key * 'Value> -> System.Collections.Generic.IDictionary<'Key,'Value> (requires equality)
<summary>Builds a read-only lookup table from a sequence of key/value pairs. The key objects are indexed using generic hashing and equality.</summary>
val toJson : x:'t -> System.Json.JsonValue (requires member ToJson)
<summary> Maps a value to Json </summary>
val toConcrete : d:(System.Collections.Generic.IReadOnlyDictionary<'c,'d> -> 'e ParseResult) * e:('f -> 'g) -> ConcreteCodec<System.Collections.Generic.KeyValuePair<'c,'d> list,'h list,'e,'f> (requires equality and member ToList)
<summary> Wraps a pair of functions into a ConcreteCodec </summary>
val w : float
val l : float
val r : float
val w2 : float
val h : float
val parsedShapedD : ShapeD list ParseResult
type ShapeD = | Rectangle of width: float * length: float | Circle of radius: float | Prism of width: float * float * height: float static member JsonObjCodec : ConcreteCodec<KeyValuePair<string,JsonValue> list,KeyValuePair<string,JsonValue> list,ShapeD,ShapeD>
namespace System
namespace System.Text
val pf : PersonF
val personBytesCodec : (byte array -> Result<PersonF,DecodeError>) * (PersonF -> byte array)
val getString : (byte array -> string)
val bytes : byte array
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)
<summary>Converts the argument to byte. This is a direct conversion for all primitive numeric types. For strings, the input is converted using <c>Byte.Parse()</c> with InvariantCulture settings. Otherwise the operation requires an appropriate static conversion method on the input type.</summary>
<param name="value">The input value.</param>
<returns>The converted byte</returns>


--------------------
[<Struct>] type byte = System.Byte
<summary>An abbreviation for the CLI type <see cref="T:System.Byte" />.</summary>
<category>Basic Types</category>


--------------------
type byte<'Measure> = byte
<summary>The type of 8-bit unsigned integer numbers, annotated with a unit of measure. The unit of measure is erased in compiled code and when values of this type are analyzed using reflection. The type is representationally equivalent to <see cref="T:System.Byte" />.</summary>
<category>Basic Types with Units of Measure</category>
type 'T array = 'T []
<summary>Single dimensional, zero-based arrays, written <c>int[]</c>, <c>string[]</c> etc.</summary>
<remarks>Use the values in the <see cref="T:Microsoft.FSharp.Collections.ArrayModule" /> module to manipulate values of this type, or the notation <c>arr.[x]</c> to get/set array values.</remarks>
<category>Basic Types</category>
type Encoding = interface ICloneable new : unit -> unit + 2 overloads member Clone : unit -> obj member Equals : value: obj -> bool member GetByteCount : chars: nativeptr<char> * count: int -> int + 5 overloads member GetBytes : chars: nativeptr<char> * charCount: int * bytes: nativeptr<byte> * byteCount: int -> int + 7 overloads member GetCharCount : bytes: nativeptr<byte> * count: int -> int + 3 overloads member GetChars : bytes: nativeptr<byte> * byteCount: int * chars: nativeptr<char> * charCount: int -> int + 4 overloads member GetDecoder : unit -> Decoder member GetEncoder : unit -> Encoder ...
<summary>Represents a character encoding.</summary>
property Encoding.UTF8: Encoding with get
<summary>Gets an encoding for the UTF-8 format.</summary>
<returns>An encoding for the UTF-8 format.</returns>
(extension) Encoding.GetString(bytes: inref<System.Buffers.ReadOnlySequence<byte>>) : string
Encoding.GetString(bytes: System.ReadOnlySpan<byte>) : string
Encoding.GetString(bytes: byte []) : string
Encoding.GetString(bytes: nativeptr<byte>, byteCount: int) : string
Encoding.GetString(bytes: byte [], index: int, count: int) : string
property PersonF.JsonObjCodec: (System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue> -> Result<PersonF,DecodeError>) * (PersonF -> System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>) with get
val jsonObjToValueCodec : (#System.Json.JsonValue -> Result<System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,DecodeError>) * (#System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue> -> System.Json.JsonValue)
<summary> A pair of functions representing a codec to encode a Dictionary into a Json value and the other way around. </summary>
val jsonValueToTextCodec : (string -> Result<System.Json.JsonValue,DecodeError>) * (System.Json.JsonValue -> string)
<summary> A pair of functions representing a codec to encode a Json value to a Json text and the other way around. </summary>
val invmap : f:('T -> 'U) -> g:('U -> 'T) -> r:'a * w:'c -> 'b * 'd (requires member Contramap and member Map)
<summary> Turns a Codec into another Codec, by mapping it over an isomorphism. </summary>
(extension) Encoding.GetBytes(chars: inref<System.Buffers.ReadOnlySequence<char>>) : byte []
   (+0 other overloads)
Encoding.GetBytes(s: string) : byte []
   (+0 other overloads)
Encoding.GetBytes(chars: char []) : byte []
   (+0 other overloads)
(extension) Encoding.GetBytes(chars: inref<System.Buffers.ReadOnlySequence<char>>, writer: System.Buffers.IBufferWriter<byte>) : int64
   (+0 other overloads)
(extension) Encoding.GetBytes(chars: inref<System.Buffers.ReadOnlySequence<char>>, bytes: System.Span<byte>) : int
   (+0 other overloads)
(extension) Encoding.GetBytes(chars: System.ReadOnlySpan<char>, writer: System.Buffers.IBufferWriter<byte>) : int64
   (+0 other overloads)
Encoding.GetBytes(chars: System.ReadOnlySpan<char>, bytes: System.Span<byte>) : int
   (+0 other overloads)
Encoding.GetBytes(s: string, index: int, count: int) : byte []
   (+0 other overloads)
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
   (+0 other overloads)
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
   (+0 other overloads)
val bytePerson : byte array
val encode : 'a * e:Encoder<'o,'a0> -> a:'a0 -> 'o
val p' : PersonF ParseResult
val decode : d:Decoder<'i,'a> * 'a0 -> i:'i -> 'a ParseResult
val personBytesCodec2 : (byte array -> Person ParseResult) * (Person -> byte array)
property Person.JsonObjCodec: ConcreteCodec<System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,System.Collections.Generic.KeyValuePair<string,System.Json.JsonValue> list,Person,Person> with get