2016-10-22 60 views
4

如果我有一個特定的標記聯合類型,如Shape這裏,我將如何構建它在Elm中的JSON解碼器?如何在Elm中解碼標記的聯合類型?

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

type alias Circle = { radius: Int } 

type Shape 
    = ShapeRectangle Rectangle 
    | ShapeCircle Circle 

回答

7

鑑於你的JSON看起來像

{ "radius" : 10 }

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

,那麼這將這樣的伎倆

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) 

還有一些其他的東西:我經常添加'type'和'tag'字段以幫助消除具有常見字段名稱的數據類型時的歧義。該JSON然後貌似

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

另外,我覺得:=field在即將到來的0.18版本來替換。

問候,

邁克爾

1

米歇爾·托馬的回答這裏一片燦爛的光芒。

`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 

可以使用Json.Decode.mapandThen喜歡這個標籤解碼值