#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:
- 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:
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<'Key, 'Value>
</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<value> 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<'Key, 'Value>
</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