Marcelo Lazaroni Marcelo Lazaroni - 1 month ago 21
JSON Question

How to decode tagged union types in Elm?

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

Answer

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

Comments