How to decode labeled union types in Elm?

If I have a specific type of connection with tags, for example Shapehere, how can I build 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
+4
source share
2 answers

Given that your JSON looks like

{ "radius" : 10 }

or

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

Then it 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 few additional things: I often add a type and tag field to help disambiguate when I have data types with common field names. Then JSON looks like

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

In addition, I think it :=will be replaced by fieldthe upcoming version 0.18.

Hi,

Michael

+8
source

Michelle Tom’s answer shone a big light.

Json.Decode.map andThen :

`andThen` \x -> decode (MyTag x)

- andThen Json.Decode.Pipeline

import Json.Decode exposing ( Decoder, decodeString, int, andThen, oneOf )
import Json.Decode.Pipeline exposing ( decode, required )

import Html

main =
  let
    decoded = decodeString decodeShape "{ \"radius\": 2 }"
   in
     case decoded of
       Ok shape ->
         Html.text <| toString shape

       Err error ->
         Html.text error

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

type alias Circle = { radius: Int }

type Shape
    = ShapeRectangle Rectangle
    | ShapeCircle Circle



decodeShape : Decoder Shape
decodeShape =
  oneOf
    [ decodeRectangle `andThen` \x -> decode (ShapeRectangle x)
    , decodeCircle `andThen` \x -> decode (ShapeCircle x)
    ]



decodeRectangle : Decoder Rectangle
decodeRectangle =
    decode Rectangle
        |> required "width" int
        |> required "height" int




decodeCircle : Decoder Circle
decodeCircle =
    decode Circle
         |> required "radius" int
+1

Source: https://habr.com/ru/post/1658541/


All Articles