2016-10-22 5 views

答えて

7

{ "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) 
を行います

2つの追加事項:共通のフィールド名を持つデータ型を持つときに明確にするために、「型」フィールドと「タグ」フィールドを追加することがよくあります。 JSONはその後、

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

のように見えます。また、私は:=は、今後の0.18のリリースでfieldによって置き換えられると思います。

よろしく、

マイケル

1

ミシェル・トーマの答えはここに偉大な光を照らしました。

あなたはこのよう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 
を使用したソリューションであります
関連する問題