结构不匹配而解析JSON
问题描述:
我试图解析JSON文件,并将其展示给用户,这里的简化版本结构不匹配而解析JSON
{
"posts": [{
// some properties
comments: {
// some more properties
}
}
这是我的代码,我知道这是一个很多我真的不知道为了隔离问题要删除什么,每次尝试时我都会得到一个不同的错误,这似乎导致我无处可去。
type Action
= NoOp
| GetPosts
| ShowPosts (Maybe { posts : List Post.Model })
init =
({ posts = Nothing }, Effects.none)
update action model =
case action of
NoOp ->
(model, Effects.none)
GetPosts ->
({ model | posts = Nothing }, getPosts)
ShowPosts maybePosts ->
({ model | posts = maybePosts }, Effects.none)
view address model =
div
[]
[ button [ onClick address GetPosts ] [ text "Click to get posts!" ]
, viewPosts model.posts
]
viewPosts maybePosts =
case maybePosts of
Nothing ->
div [] [ text "No posts to display. Try clicking the button" ]
Just posts ->
ul [] (List.map Post.view posts)
-- This is the key to map the result of the HTTP GET to an Action
-- Note: Task.toMaybe swallows any HTTP or JSON decoding errors
getPosts : Effects Action
getPosts =
Http.get decoderColl "./posts.json"
|> Task.toMaybe
|> Task.map ShowPosts
|> Effects.task
type alias PostListContainerModel =
{ posts : List Post.Model }
postDecoder : Decoder Post.Model
postDecoder =
Decode.object5
Post.Model
("img" := Decode.string)
("text" := Decode.string)
("source" := Decode.string)
("date" := Decode.string)
("comments" := Decode.list commentDecoder)
commentDecoder : Decoder Comment.Model
commentDecoder =
Decode.object2
Comment.Model
("text" := Decode.string)
("date" := Decode.string)
decoderColl : Decoder PostListContainerModel
decoderColl =
Decode.object1
PostListContainerModel
("posts" := Decode.list postDecoder)
我从编译器收到此错误
功能
start
期待的说法是:{ ... , view : Signal.Address Action -> { posts : Maybe { posts : List Post.Model } } -> Html }
但它是:
{ ... , view : Signal.Address Action -> { posts : Maybe (List Post.Model) } -> Html }
我不明白在view
的定义中额外的{ posts : Maybe
来自哪里。
一些额外的背景前面的问题:Parsing nested JSON in Elm
UPDATE:
得到了榆树社区谷歌组中的答案,这里的要点https://gist.github.com/rundis/23d7ef6ea42842e6f527
答
我认为ShowPosts
的定义越来越在办法。你有这样的:
ShowPosts (Maybe { posts : List Post.Model })
但是这或许应该是这样的:
ShowPosts (Maybe (List Post.Model))
做出这样的转变将导致你必须更新其他一些地方,而是遵循编译器的消息,它应该引领你到正确的地方。
其中一个需要更新的地方是getPosts
,您需要从该包装器对象中取出帖子列表。这应该是这样简单:
|> Task.map (ShowPosts << .posts)
嘿!谢谢:)是的,这是我尝试过的一件事,但我得到了一个我并不真正了解的错误。我会更努力。 –
我试着改变这个定义'type alias PostListContainerModel = List Post.Model',因为它为我提供了这种方式,但是没有,我得到'无法找到变量'PostListContainerModel',这使我更困惑。 –
我已经更新了答案,以包含一个不需要传递'PostListContainerModel'的例子。这对于解码很有用,但实际上,通过更新'getPosts',你可以避免在其他地方使用'List Post.Model'来传递它。 –