type User
= Anonymous
| Named {name : String, email : String}
Json.Decode.object2
不適合在這裏,因爲它的第一個參數類型是(a -> b -> c)
但Named
具有{ email : String, name : String } -> User
型。
如何解碼爲用戶?
type User
= Anonymous
| Named {name : String, email : String}
Json.Decode.object2
不適合在這裏,因爲它的第一個參數類型是(a -> b -> c)
但Named
具有{ email : String, name : String } -> User
型。
如何解碼爲用戶?
這樣做的另一種方法可能是定義一個函數,接受名稱和電子郵件並返回您的Named
構造:
userDecoder : Decoder User
userDecoder =
let
named =
object2
(\n e -> Named { name = n, email = e })
("name" := string)
("email" := string)
in
oneOf [ null Anonymous, named ]
由於您的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]" }])
謝謝您的完整解答。我猜想這是不可能的。我將重新考慮我的模型,並嘗試不使用數據構造函數的記錄。 – ztsu
你可以提供既代表一個匿名的,並命名爲用戶的JSON的例子嗎? –
'[{「user」:null},{「user」:{「name」:「John Doe」,「email」:「[email protected]」}}]' – ztsu