如何实现一个由于其中一个字段具有相同类型而调用自身的解码器?
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)
Run Code Online (Sandbox Code Playgroud)
以下行导致问题:
(field "Subscriptions" <| Decode.list providerDecoder)
(field "Followers" <| Decode.list providerDecoder)
Run Code Online (Sandbox Code Playgroud)
providerDecoder直接根据自身定义,造成无限
总之,我不知道如何在保留JsonProvider类型的同时解决此错误.
附录:
type JsonProvider
= JsonProvider
{ profile : JsonProfile
, topics : List JsonTopic
, links : JsonLinks
, recentLinks : List JsonLink
, subscriptions : List JsonProvider
, followers : List JsonProvider
}
Run Code Online (Sandbox Code Playgroud)
当您编写递归JSON解码器时,您通常必须依赖Json.Decode.lazy.您可以将这两行写为:
(field "Subscriptions" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
(field "Followers" <| Decode.list (Decode.lazy (\_ -> providerDecoder)))
Run Code Online (Sandbox Code Playgroud)
一旦你改变它,你会看到另一个错误信息弹出关于不匹配的类型,那是因为你正在使用一个构造函数联合类型,它有一个记录作为参数(这在编写递归记录类型时是必要的).在这种情况下,我通常将构造函数和记录类型分开,如下所示:
type JsonProvider
= JsonProvider JsonProviderFields
type alias JsonProviderFields =
{ profile : JsonProfile
, topics : List JsonTopic
, links : JsonLinks
, recentLinks : List JsonLink
, subscriptions : List JsonProvider
, followers : List JsonProvider
}
Run Code Online (Sandbox Code Playgroud)
现在您可以重写提供程序解码器以首先解码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
Run Code Online (Sandbox Code Playgroud)