2016-02-06 17 views
5

Iは、以下のようなELM型にJSONをデコードする必要があります型の値にエルム複雑なカスタムJSONデコーダ

タイプ

type User = Anonymous | LoggedIn String 

type alias Model = 
    { email_id : User 
    , id : Id 
    , status : Int 
    , message : String 
    , accessToken : AccessToken 
    } 

JSONメッセージ1

{ 
    "status": 0, 
    "message": "Error message explaining what happened in server" 
} 

Model { 
    "email_id": Anonymous 
    , id: 0 
    , status: 0 
    , message: json.message 
    , accessToken: "" 
} 

JSONメッセージ2種類の値に

{ 
    "status": 1, 
    "email_id": "[email protected]" 
    "token": "asdfaz.adfasggwegwegwe.g4514514ferf" 
    "id": 234 
} 

Model { 
    "email_id": LoggedIn json.email_id 
    , id: json.id 
    , status: json.status 
    , message: "" 
    , accessToken: json.token 
} 

デコーダ情報上方

は、 "メッセージ" は、必ずしも存在せず、EMAIL_ID/ID /トークンは、常にではありませんプレゼント。ニレ

答えて

8

Json.Decode.andThenに条件付きデコードのこのタイプを行うにはどのように

あなたは、フィールドの値に基づいて条件付き解析を行うことができます。この場合、「ステータス」フィールドの値を最初に引き出したい場合は10かに基づいてandThenを個別に処理するように見えます。

編集2016年12月15日:素晴らしい解決策のために再びELM-0.18

import Html as H 
import Json.Decode exposing (..) 

type User = Anonymous | LoggedIn String 

type alias Id = Int 

type alias AccessToken = String 

type alias Model = 
    { email_id : User 
    , id : Id 
    , status : Int 
    , message : String 
    , accessToken : AccessToken 
    } 

modelDecoder : Decoder Model 
modelDecoder = 
    (field "status" int) |> andThen modelDecoderByStatus 

modelDecoderByStatus : Int -> Decoder Model 
modelDecoderByStatus status = 
    case status of 
    0 -> 
     map5 
     Model 
     (succeed Anonymous) 
     (succeed 0) 
     (succeed status) 
     (field "message" string) 
     (succeed "") 
    1 -> 
     map5 
     Model 
     (map LoggedIn (field "email_id" string)) 
     (field "id" int) 
     (succeed status) 
     (succeed "") 
     (field "token" string) 
    _ -> 
     fail <| "Unknown status: " ++ (toString status) 

main = H.div [] 
    [ H.div [] [ decodeString modelDecoder msg1 |> Result.toMaybe |> Maybe.withDefault emptyModel |> toString |> H.text ] 
    , H.div [] [ decodeString modelDecoder msg2 |> Result.toMaybe |> Maybe.withDefault emptyModel |> toString |> H.text ] 
    ] 

emptyModel = Model Anonymous 0 0 "" "" 

msg1 = """ 
{ 
    "status": 0, 
    "message": "Error message explaining what happened in server" 
} 
""" 

msg2 = """ 
{ 
    "status": 1, 
    "email_id": "[email protected]" 
    "token": "asdfaz.adfasggwegwegwe.g4514514ferf" 
    "id": 234 
} 
""" 
+0

感謝を更新しました。できます。 Tasksと 'andThen'がここで使用されている理由については、少し不明なようにJSONデコーダの動作を理解するためにいくつかのリンクを渡すことができますか?それは非常に一般的な目的ではありますが、私はTasksをタスクとの約束と考えていました。 –

+1

リンクをもう一度見てください。それは['Task.andThen'](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Task#andThen)を使用していないので、同じ関数を使用していますJsonデコーダの名前。両方のAPIセットを見てみると、 '成功'と '失敗'のような類似点があります。これは関数型言語の共通のパターンである基本的なMonadパターンと整列していますが、ElmはMonadsを理解するのは敢えて避けますが、Monadsを理解するのは大変です。あなたはJsonを解析するためにMonadsを理解する必要はありません。 –

関連する問題