xyncro / chiron

JSON for F#
https://xyncro.tech/chiron
MIT License
175 stars 41 forks source link

Sample deserialise union? #14

Closed haf closed 9 years ago

haf commented 9 years ago

You have a serialise example; could you show the deserialise example?

type TestUnion =
    | One of string
    | Two of int * bool

    static member ToJson (x: TestUnion) =
        match x with
        | One (s) -> Json.write "one" s
        | Two (i, b) -> Json.write "two" (i, b)
haf commented 9 years ago

So, no answer, eh? That meant I had to think for myself. Evil you!

I might have a few options... The active pattern in particular makes it very F#.

Alternative 1, pattern matching, vanilla:


    static member FromJson (_ : TestUnion) =
      Json.tryRead "one"
      >>= (function
          | Some s -> Json.init (One s)
          | None   -> Json.read "two" |> Json.map Two)

Alternative 2, effing functional:

    static member FromJson (_ : TestUnion) =
      Json.tryRead "one"
      >>= Option.fold (fun s t -> Json.init (One t)) (Json.read "two" |> Json.map Two)

Alternative 3, wooorkflows:


    static member FromJson (_ : TestUnion) =
      json {
        let! mone = Json.tryRead "one"
        match mone with
        | Some s -> return One s
        | None ->
          let! x = Json.read "two"
          return Two x
      }

My favorite, the active pattern variant:

    static member FromJson (_ : TestUnion) =
      function
      | Prop "one" str as json ->
        Json.init (One str) json
      | Prop "two" (i, b) as json ->
        Json.init (Two (i, b)) json
      | json ->
        Json.error (sprintf "couldn't deserialise %A to TestUnion" json) json

Using this discriminated union:

let inline (|Prop|_|) key =
  Lens.getPartial (objectKeyPLens key)
  >> Option.bind Json.tryDeserialize
kolektiv commented 9 years ago

Ah, I have been off-grid for a few days, rather than employing any kind of socratic silence :) Back now though! I would personally probably go for something like alternative 1. Although I'm just going to have a quick play with a different idea...

kolektiv commented 9 years ago

Hmmm. Looking at it more now I think that the active pattern variant is objectively the "best" as it'll scale much better to unions with N cases, the others become unwieldy (as would my other idea). I wonder if we can sensible include that active pattern in the library (called something like ObjectKey or something perhaps?)

I think that works nicely...

haf commented 9 years ago

Cool, we agree then! =) I have a DU with about 25 cases I need this for ;)

I believe they're called 'properties' in JS lang?

kolektiv commented 9 years ago

I'm not sure I've seen much consistency! "Property" would be cool i think, provided it isn't one of the uncountable f# reserved keywords...

On 20 April 2015 at 22:24, Henrik Feldt notifications@github.com wrote:

Cool, we agree then! =) I have a DU with about 25 cases I need this for ;)

I believe they're called 'properties' in JS lang?

— Reply to this email directly or view it on GitHub https://github.com/xyncro/chiron/issues/14#issuecomment-94572741.

kolektiv commented 9 years ago

I've included the "Property" pattern in the pull request #30 (combined changes). It's a neat little addition.