如果我有一個特定的標記聯合類型,如Shape
這裏,我將如何構建它在Elm中的JSON解碼器?如何在Elm中解碼標記的聯合類型?
type alias Rectangle = { width : Int, height : Int }
type alias Circle = { radius: Int }
type Shape
= ShapeRectangle Rectangle
| ShapeCircle Circle
如果我有一個特定的標記聯合類型,如Shape
這裏,我將如何構建它在Elm中的JSON解碼器?如何在Elm中解碼標記的聯合類型?
type alias Rectangle = { width : Int, height : Int }
type alias Circle = { radius: Int }
type Shape
= ShapeRectangle Rectangle
| ShapeCircle Circle
鑑於你的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版本來替換。
問候,
邁克爾
米歇爾·托馬的回答這裏一片燦爛的光芒。
`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.map
或andThen
喜歡這個標籤解碼值