代码之家  ›  专栏  ›  技术社区  ›  Ananth

用于具有数据的联合类型的Elm JSON解码器

  •  1
  • Ananth  · 技术社区  · 7 年前

    我的json如下所示:

    {"name": "providerWithVal", "value": "example"}
    

    或者像这样:

    {"name": "provider2"}
    

    {"name": "provider3"}
    

    我的Elm联合类型定义如下:

    type Provider
        = ProviderWithVal String
        | Provider2
        | Provider3
    

    我可以为联合类型编写一个解码器,而无需附加数据。但是 ProviderWithVal

    import Json.Decode as D
    
    providerDecoder : D.Decoder Provider
    providerDecoder =
        D.field "name" D.string |> D.andThen providerNameDecoder
    
    providerNameDecoder : String -> D.Decoder Provider
    providerNameDecoder string =
        case string of
            "providerWithVal" -> D.succeed ProviderWithVal
            "provider2" -> D.succeed Provider2
            "provider3" -> D.succeed Provider3
            _ -> D.fail <| "Invalid provider: " ++ string
    
    1 回复  |  直到 7 年前
        1
  •  5
  •   Simon H    6 年前

    你的问题的快速解决方法是替换 D.succeed ProviderWithVal D.map ProviderWithVal (D.field "value" Decode.string)

    但我会创建一个帮助器来匹配目标字符串,然后按以下方式使用它:

    decoder =
        Decode.oneOf [ decodeWithVal, decodeP2, decodeP3 ]
    
    
    decodeWithVal =
        exactMatch (Decode.field "name" Decode.string)
            "providerWithVal"
            (Decode.map ProviderWithVal <| Decode.field "value" Decode.string)
    
    
    decodeP2 =
        exactMatch (Decode.field "name" Decode.string) "provider2" (Decode.succeed Provider2)
    
    
    decodeP3 =
        exactMatch (Decode.field "name" Decode.string) "provider3" (Decode.succeed Provider3)
    
    
    exactMatch : Decoder String -> String -> Decoder a -> Decoder a
    exactMatch matchDecoder match dec =
        matchDecoder
            |> Decode.andThen
                (\str ->
                    if str == match then
                        dec
    
                    else
                        Decode.fail <| "[exactMatch] tgt: " ++ match ++ " /= " ++ str
                )
    
    推荐文章