【问题标题】:How to a decode Json.Decode.Value into tagged union type in elm 0.19?如何将 Json.Decode.Value 解码为 elm 0.19 中的标记联合类型?
【发布时间】:2019-07-28 21:09:32
【问题描述】:

我明白了

我认为第一个与 elm 0.19 无关。我在NoRedInk/elm-json-decode-pipeline 中找不到decode 函数,我不相信:= 中缀运算符仍然有效。

第二个解决了基于 JSON 字段的值的条件解码略有不同的问题。

如果我有来自端口和以下类型的数据:

import Json.Decode 暴露(Decoder,map,oneOf,string,succeed,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 = "" })

真的很丑,感觉不对。

【问题讨论】:

    标签: json functional-programming elm decoder


    【解决方案1】:

    您已经完成了所有艰苦的工作。这应该是你现在所需要的。注意.map 是处理案例陈述的快捷方式。

    import Json.Decode as Decode exposing (Decoder)
    statusDecoder =
        Decode.oneOf
            [ Decode.map Authenticated dataDecoder
            , Decode.map Unauthenticated <| Decode.maybe errorDecoder
            ]
    

    【讨论】:

      【解决方案2】:

      我采用的解决方案是使用Json.Decode.mapDecoder DataDecoder Error 类型转换为Decoder Status 类型,使用Status 类型构造函数Authenticated dataUnauthenticated Maybe error

      然后我可以使用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
              ]
      

      【讨论】:

        猜你喜欢
        • 2017-03-04
        • 1970-01-01
        • 2020-10-16
        • 1970-01-01
        • 1970-01-01
        • 2020-09-22
        • 1970-01-01
        • 2021-11-23
        • 1970-01-01
        相关资源
        最近更新 更多