[英]How to a decode Json.Decode.Value into tagged union type in elm 0.19?
我懂了
我不相信第一个与 elm 0.19 相关。 我在NoRedInk/elm-json-decode-pipeline 中找不到decode
函数,我不相信:=
缀运算符仍然有效。
第二个解决了根据 JSON 字段的值进行条件解码的稍微不同的问题。
如果我有数据通过端口和以下类型:
导入 Json.Decode 暴露 (Decoder, map, oneOf, string, success, andThen, map2, map4)
import Json.Decode exposing (Decoder, andThen, map, map2, map4, oneOf, string, succeed, field)
port loginResponse : (Value -> msg) -> Sub msg
type Status
= Authenticated Data
| Unauthenticated (Maybe Error)
type alias Data =
{ accessToken : String
, email : String
, name : String
, nickname : String
}
dataDecoder : Decoder Data
dataDecoder =
map4 Data
(field "accessToken" string)
(field "email" string)
(field "name" string)
(field "nickname" string)
type alias Error =
{ error : String
, errorDescription : String
}
errorDecoder : Decoder Error
errorDecoder =
map2 Error
(field "error" string)
(field "errorDescription" string)
如何为标记联合类型Status
编写解码器以解码从端口返回的数据?
到目前为止我得到的最好的是
statusDecoder : Decoder Status
statusDecoder =
oneOf
[ dataDecoder andThen (\data -> succeed (Authenticated data)
, errorDecoder andThen (\error -> succeed (Unauthenticated (Just error)))
]
这是无效的,或
getStatus : Json.Decode.Value -> Status
getStatus value =
let
decodedData =
decodeValue dataDecoder value
in
case decodedData of
Ok data ->
Authenticated data
Err _ ->
let
decodedError =
decodeValue errorDecoder value
in
case decodedError of
Ok error ->
Unauthenticated (Just error)
Err err ->
Unauthenticated (Just { error = "There was a problem decoding the JSON", errorDescription = "" })
这真的很丑,感觉不对。
你已经完成了所有的艰苦工作。 这应该就是你现在所需要的。 注意.map
是执行 case 语句的快捷方式。
import Json.Decode as Decode exposing (Decoder)
statusDecoder =
Decode.oneOf
[ Decode.map Authenticated dataDecoder
, Decode.map Unauthenticated <| Decode.maybe errorDecoder
]
我采用的解决方案是使用Json.Decode.map使用Status
类型构造函数Authenticated data
和Unauthenticated Maybe error
将Decoder Data
和Decoder Error
类型转换为Decoder Status
类型。
然后我可以使用Json.Decode.oneOf函数根据数据的形状解码成一个或另一个,因为两个解码器现在都是相同类型的Decoder Status
。
dataDecoder : Decoder Status
dataDecoder =
map Authenticated <|
map4 Data
(field "accessToken" string)
(field "email" string)
(field "name" string)
(field "nickname" string)
errorDecoder : Decoder Status
errorDecoder =
map Unauthenticated <|
maybe <|
map2 Error
(field "error" string)
(field "errorDescription" string)
statusDecoder : Decoder Status
statusDecoder =
oneOf [ dataDecoder, errorDecoder ]
为简洁起见,您可以使用Json.Decode.decodeValue函数和上面定义的statusDecoder
函数来解码从更新函数中的端口出来的Json.Decode.Value
。
-- UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ReceiveLoginResponse response ->
let
decodedResponse = decodeValue Auth.statusDecoder response
in
case decodedResponse of
Ok status ->
( { model
| authStatus = status
}
, Cmd.none
)
...
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch
[ loginResponse ReceiveLoginResponse
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.