[英]How to a decode Json.Decode.Value into tagged union type in elm 0.19?
I see我懂了
I don't believe the first is relevant for elm 0.19.我不相信第一个与 elm 0.19 相关。 I could not find a
decode
function in NoRedInk/elm-json-decode-pipeline and I do not believe the :=
infix operator is still valid.我在NoRedInk/elm-json-decode-pipeline 中找不到
decode
函数,我不相信:=
缀运算符仍然有效。
The second addresses the slightly different question of conditionally decoding based on the value of a JSON field.第二个解决了根据 JSON 字段的值进行条件解码的稍微不同的问题。
If I have data coming over a port and the following types:如果我有数据通过端口和以下类型:
import Json.Decode exposing (Decoder, map, oneOf, string, succeed, andThen, map2, map4)导入 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)
How can I write a decoder for tagged union type Status
to decode the data coming back in from the port?如何为标记联合类型
Status
编写解码器以解码从端口返回的数据?
Best I got so far is something like到目前为止我得到的最好的是
statusDecoder : Decoder Status
statusDecoder =
oneOf
[ dataDecoder andThen (\data -> succeed (Authenticated data)
, errorDecoder andThen (\error -> succeed (Unauthenticated (Just error)))
]
which isn't valid, or这是无效的,或
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 = "" })
which is really ugly and doesn't feel right.这真的很丑,感觉不对。
you've done all the hard work.你已经完成了所有的艰苦工作。 This should be all you need now.
这应该就是你现在所需要的。 Note
.map
is the quick way to do your case statement stuff.注意
.map
是执行 case 语句的快捷方式。
import Json.Decode as Decode exposing (Decoder)
statusDecoder =
Decode.oneOf
[ Decode.map Authenticated dataDecoder
, Decode.map Unauthenticated <| Decode.maybe errorDecoder
]
The solution I went with is to use Json.Decode.map to translate the Decoder Data
and Decoder Error
types to Decoder Status
types using the Status
type constructors Authenticated data
and Unauthenticated Maybe error
.我采用的解决方案是使用Json.Decode.map使用
Status
类型构造函数Authenticated data
和Unauthenticated Maybe error
将Decoder Data
和Decoder Error
类型转换为Decoder Status
类型。
I can then use the Json.Decode.oneOf function to decode into one or the other depending on the shape of the data because both decoders are now of the same type 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 ]
For brevity you can then use the Json.Decode.decodeValue function with the statusDecoder
function defined above to decode the Json.Decode.Value
coming out of the port in your update function.为简洁起见,您可以使用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.