2016-05-30 4 views
1

その最初の引数の型が(a -> b -> c)ですが{ email : String, name : String } -> UserタイプをNamed持っているのでタイプデータコンストラクタで作成したJSONをデコードする方法は?

type User 
    = Anonymous 
    | Named {name : String, email : String} 

Json.Decode.object2がここに合わないがあります。

ユーザーにデコードする方法は?

+2

は匿名と名前付きユーザーの両方を表現するあなたのJSONの例を提供することができますか? –

+0

'[{" user ":null}、{" user ":{" name ":" John Doe "、" email ":" [email protected] "}}]' – ztsu

答えて

3

これを行うための別の方法は、名前とメールアドレスを受け入れ、あなたのを返す関数を定義することができコンストラクタ:

userDecoder : Decoder User 
userDecoder = 
    let 
    named = 
     object2 
     (\n e -> Named { name = n, email = e }) 
     ("name" := string) 
     ("email" := string) 
    in 
    oneOf [ null Anonymous, named ] 
2

Namedコンストラクタはパラメータとしてレコードを取得するため、名前と電子メールレコードのタイプエイリアスを作成するのに少し面倒かもしれません。

type alias NamedUserInfo = 
    { name : String 
    , email : String 
    } 

その後、エイリアスを使用するようにUserを再定義することができます:

type User 
    = Anonymous 
    | Named NamedUserInfo 

を上記厳密には必要ではないですが、私はレコードタイプをエイリアシングする道を多くの点で有用であることがわかっていることがわかります。それは私たちに、私たちは明らかにデコーダを定義することができますコンストラクタNamedUserInfoを与えるので、ここではそれが便利です:

import Json.Decode exposing (..) 

namedUserInfoDecoder : Decoder NamedUserInfo 
namedUserInfoDecoder = 
    object2 
    NamedUserInfo 
    ("name" := string) 
    ("email" := string) 

そして最後に、ユーザーのデコーダは、このように構成することができます

userDecoder : Decoder User 
userDecoder = 
    oneOf 
    [ null Anonymous 
    , object1 Named namedUserInfoDecoder 
    ] 

あなたはあなたの例を実行することができますこのような簡単なテストを通じて:

exampleJson = 
    """ 
    [{"user":null}, {"user": {"name": "John Doe", "email": "[email protected]"}}] 
    """ 

main = 
    text <| toString <| decodeString (list ("user" := userDecoder)) exampleJson 

-- Ouputs: 
-- Ok ([Anonymous,Named { name = "John Doe", email = "[email protected]" }]) 
+0

完全な回答ありがとうございます。私はそれが可能ではないと推測しました。モデルを再考し、データコンストラクタでレコードを使用しないようにします。 – ztsu

関連する問題