如何实现一个由于其中一个字段具有相同类型而调用自身的解码器?

时间:2017-09-15 02:12:12

标签: elm

如何实现一个由于其中一个字段具有相同类型而调用自身的解码器?

providerDecoder : Decoder JsonProvider
providerDecoder =
    Decode.map6 JsonProvider
        (field "Profile" profileDecoder)
        (field "Topics" <| Decode.list topicDecoder)
        (field "Links" <| linksDecoder)
        (field "RecentLinks" <| Decode.list linkDecoder)
        (field "Subscriptions" <| Decode.list providerDecoder)
        (field "Followers" <| Decode.list providerDecoder)

以下几行导致问题:

(field "Subscriptions" <| Decode.list providerDecoder)
(field "Followers" <| Decode.list providerDecoder)
  

providerDecoder直接根据自身定义,导致   无限

总之,我不确定如何在保留JsonProvider类型的同时解决此错误。

附录

type JsonProvider
    = JsonProvider
        { profile : JsonProfile
        , topics : List JsonTopic
        , links : JsonLinks
        , recentLinks : List JsonLink
        , subscriptions : List JsonProvider
        , followers : List JsonProvider
        }

1 个答案:

答案 0 :(得分:5)

编写递归JSON解码器时,通常需要依赖Json.Decode.lazy。您可以将这两行写为:

(field "Subscriptions" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
(field "Followers" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))

一旦你改变了,你会看到另一个关于不匹配的类型的错误信息,那是因为你正在使用一个构造函数联合类型,它有一个记录作为参数(在编写递归记录时这是必要的)类型)。在这种情况下,我通常将构造函数和记录类型分开,如下所示:

type JsonProvider
    = JsonProvider JsonProviderFields

type alias JsonProviderFields =
    { profile : JsonProfile
    , topics : List JsonTopic
    , links : JsonLinks
    , recentLinks : List JsonLink
    , subscriptions : List JsonProvider
    , followers : List JsonProvider
    }

现在您可以重写提供程序解码器,首先解码JsonProviderFields记录,然后将其映射到JsonProvider

providerDecoder : Decoder JsonProvider
providerDecoder =
    Decode.map6 JsonProviderFields
        (field "Profile" profileDecoder)
        (field "Topics" <| Decode.list topicDecoder)
        (field "Links" <| linksDecoder)
        (field "RecentLinks" <| Decode.list linkDecoder)
        (field "Subscriptions" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
        (field "Followers" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
        |> Decode.map JsonProvider