Fleece


#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.

But for those cases where we don't have control over the types (extension members won't be taken into account) we can explicitly specify combinators.

To do so, a set of the available functions exists, ending with the With suffix, which accepts a combinator as first parameter:

type Color = Red | Blue | White

type Car = {
    Id : string
    Color : Color
    Kms : int }

let colorDecoder = function
    | JString "red"   -> Decode.Success Red
    | JString "blue"  -> Decode.Success Blue
    | JString "white" -> Decode.Success White
    | JString  x as v -> Decode.Fail.invalidValue v ("Wrong color: " + x)
    | x               -> Decode.Fail.strExpected  x

let colorEncoder = function
    | Red   -> JString "red"
    | Blue  -> JString "blue"
    | White -> JString "white"

let colorCodec = colorDecoder, colorEncoder

let [<GeneralizableValue>]carCodec<'t> =
    fun i c k -> { Id = i; Color = c; Kms = k }
    |> withFields
    |> jfieldWith JsonCodec.string "id"    (fun x -> x.Id)
    |> jfieldWith colorCodec       "color" (fun x -> x.Color)
    |> jfieldWith JsonCodec.int    "kms"   (fun x -> x.Kms)
    |> Codec.compose jsonObjToValueCodec

let car = { Id = "xyz"; Color = Red; Kms = 0 }

let jsonCar = Codec.encode carCodec car
// val jsonCar : JsonValue = {"id": "xyz", "color": "red", "kms": 0}
namespace Fleece
module SystemJson from Fleece
type Color = | Red | Blue | White
union case Color.Red: Color
union case Color.Blue: Color
union case Color.White: Color
type Car = { Id: string Color: Color Kms: int }
Car.Id: 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>
Multiple items
Car.Color: Color

--------------------
type Color = | Red | Blue | White
Car.Kms: int
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>
val colorDecoder : _arg1:System.Json.JsonValue -> Result<Color,DecodeError>
Multiple items
val JString : x:string -> System.Json.JsonValue

--------------------
active recognizer JString: System.Json.JsonValue -> Choice<System.Collections.Generic.IReadOnlyList<System.Json.JsonValue>,System.Collections.Generic.IReadOnlyDictionary<string,System.Json.JsonValue>,System.Json.JsonPrimitive,bool,string,unit>
module Decode from Fleece.SystemJson
Multiple items
val Success : x:'a -> Result<'a,'b>

--------------------
active recognizer Success: Result<'a,'b> -> Choice<'a,'b>
val x : string
val v : System.Json.JsonValue
module Fail from Fleece.SystemJson.Decode
val invalidValue : v:System.Json.JsonValue -> o:string -> Result<'t,DecodeError>
val x : System.Json.JsonValue
val strExpected : v:System.Json.JsonValue -> Result<'t,DecodeError>
val colorEncoder : _arg1:Color -> System.Json.JsonValue
val colorCodec : (#System.Json.JsonValue -> Result<Color,DecodeError>) * (Color -> System.Json.JsonValue)
Multiple items
type GeneralizableValueAttribute = inherit Attribute new : unit -> GeneralizableValueAttribute
<summary>Adding this attribute to a non-function value with generic parameters indicates that uses of the construct can give rise to generic code through type inference. </summary>
<category>Attributes</category>


--------------------
new : unit -> GeneralizableValueAttribute
val carCodec<'t> : (System.Json.JsonValue -> Result<Car,DecodeError>) * (Car -> System.Json.JsonValue)
val i : string
val c : Color
val k : int
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 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>
module JsonCodec from Fleece.SystemJson
val string : (#System.Json.JsonValue -> Result<string,DecodeError>) * (string -> System.Json.JsonValue)
val x : Car
Car.Color: Color
val int : (#System.Json.JsonValue -> Result<int,DecodeError>) * (int -> System.Json.JsonValue)
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 compose : ('a -> 'b) * ('e -> 'f) -> ('d -> 'c) * ('g -> 'e) -> ('a -> 'c) * ('g -> 'f) (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 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 car : Car
val jsonCar : System.Json.JsonValue
val encode : 'a * e:Encoder<'o,'a0> -> a:'a0 -> 'o