Proper JsonObjCodec with Fleece for Complex, Nested Discriminated Unions
The Problem
Fleece provides Json codecs, not string codecs, so defining ToString
and FromString
is not the way to go, unless you need them for other stuff.
The solution
Define ToJson
and OfJson
for your internal DUs. Then remove all the |> string
fragments in JsonObjCodec
body.
Here's a quick and dirty example (I advise error handling to be improved) for Comparator
:
static member ToJson x = JString (string x) static member OfJson x = match x with | JString x -> Ok (Comparator.FromString x) | _ -> Error (Uncategorized "JString expected")
Alternative solution
Leave all your internal DUs like this, but add the missing "parse" section in your JsonObjCodec
:
... with static member JsonObjCodec = (fun (a, b) -> Age (Comparator.FromString a, AgeMeasure.FromString b)) <!> jreq "Age" (function Age (comp, ageMeasure) -> Some (comp |> string, ageMeasure |> string) | _ -> None) <|> ...
this becomes a bit verbose but will do the job.
Tips
Instead of using the
<|>
operator to add codecs, you colud use thejchoice
combinator, it will read better.If you really need your
String
/FromString
methods I would suggest renamingFromString
toParse
or renaming it toTryParse
and returning an option type. This way you can take advantage of FSharpPlustryParse
function.Also, if you are using the string/parse pattern everywhere it might worth to create a codec combinator that works from transforming to/from strings. This is not an easy task but it might worth the mental effort.
For debugging stuff like this purpose, try not to open the namespace
FSharpPlus
as it contains generic definitions of operators like<|>
,<!>
and<*>
, this way you'll get better compile error messages.