如何实现一个由于其中一个字段具有相同类型而调用自身的解码器?
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
}
答案 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