Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decode tagged union types in Elm?

Tags:

json

elm

decoder

If I have a certain tagged union type, like Shape here, how would I construct a JSON decoder for it in Elm?

type alias Rectangle = { width : Int, height : Int }

type alias Circle = { radius: Int }

type Shape 
    = ShapeRectangle Rectangle 
    | ShapeCircle Circle
like image 836
Marcelo Lazaroni Avatar asked Oct 22 '16 15:10

Marcelo Lazaroni


1 Answers

Given your JSON looks like

{ "radius" : 10 }

or

{ "width" : 20, "height" : 15}

Then this will do the trick

import Json.Decode as Json exposing ((:=))

decodeShape : Json.Decoder Shape
decodeShape =
  Json.oneOf
    [ decodeShapeRectangle
    , decodeShapeCircle
    ]

decodeShapeRectangle : Json.Decoder Shape
decodeShapeRectangle =
  Json.map ShapeRectangle <|
    Json.object2 Rectangle
       ("width" := Json.int)
       ("height" := Json.int)


decodeShapeCircle : Json.Decoder Shape
decodeShapeCircle =
    Json.object1 (ShapeCircle << Circle)
         ("radius" := Json.int)

A couple of additional things: I often add a 'type' and 'tag' field to help disambiguate when I have data types with common field names. The JSON then looks like

{ "type":"shape", "tag":"circle", "radius":10 }

Also, I think := will be replaced by field in the upcoming 0.18 release.

Regards,

Michael

like image 119
Michael Thomas Avatar answered Sep 30 '22 13:09

Michael Thomas