Open gusty opened 4 years ago
The other combinator we should consider adding is being used already in our tests:
let tag prop codec =
Codec.ofConcrete codec
|> Codec.compose (
(fun o -> match IReadOnlyDictionary.tryGetValue prop o with Some (JObject a) -> Ok a | _ -> Decode.Fail.propertyNotFound prop o),
(fun x -> if Seq.isEmpty x then zero else Dict.toIReadOnlyDictionary (dict [prop, JObject x]))
)
|> Codec.toConcrete
Here's a sample usage:
type CommandParams =
| FooParams of arg1: int * arg2: int
| BarParams of arg1: string
with
static member JsonObjCodec =
jchoice
[
fun _ a -> BarParams a
<!> jreq "method" (function BarParams _ -> Some "bar" | _ -> None)
<*> tag "params" (
fun _ a -> a
<!> jreq "type" (function BarParams _ -> Some "bar.params" | _ -> None)
<*> jreq "arg1" (function BarParams (arg1 = x) -> Some x | _ -> None))
fun _ (a1, a2) -> FooParams (a1, a2)
<!> jreq "method" (function FooParams _ -> Some "foo" | _ -> None)
<*> tag "params" (
fun _ a1 a2 -> (a1, a2)
<!> jreq "type" (function FooParams _ -> Some "foo.params" | _ -> None)
<*> jreq "arg1" (function FooParams (arg1 = x) -> Some x | _ -> None)
<*> jreq "arg2" (function FooParams (arg2 = x) -> Some x | _ -> None))
]
let jsontext1 = """
{
"method": "foo",
"params": {"type": "foo.params", "arg1": 1, "arg2": 2}
}"""
let jsontext2 = """
{
"method": "bar",
"params": {"type": "bar.params", "arg1": "beep"}
}
"""
There are simpler use cases in out tests
See for instance the function proposed here
https://stackoverflow.com/questions/62287765/how-to-serialize-deserialize-this-aws-api-with-f/62291052#62291052