Alberto Zaccagni
Alberto Zaccagni

Reputation: 31560

Structure mismatch while parsing JSON

I am trying to parse a JSON file and show it to the user, here a simplified version

{
  "posts": [{ 
    // some properties 
    comments: {
      // some more properties
    }
}

This is my code, I know it's a lot I'm not really sure what to remove to isolate the problem, every time I try I get a different error that seems to lead me nowhere.

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)

I am getting this error from the compiler

Function start is expecting the argument to be:

{ ...
, view :
      Signal.Address Action
      -> { posts : Maybe { posts : List Post.Model } }
      -> Html
}

But it is:

{ ...
, view :
      Signal.Address Action -> { posts : Maybe (List Post.Model) } -> Html
}

I can't understand where that extra { posts : Maybe is coming from in the definition of view.

Previous question with some extra background: Parsing nested JSON in Elm

UPDATE:

Got an answer in the elm community google group, here's the gist https://gist.github.com/rundis/23d7ef6ea42842e6f527

Upvotes: 0

Views: 219

Answers (1)

Chad Gilbert
Chad Gilbert

Reputation: 36375

I think the definition of ShowPosts is getting in the way. You have this:

ShowPosts (Maybe { posts : List Post.Model })

But it should probably be this:

ShowPosts (Maybe (List Post.Model))

Making that change will cause you to have to update a few other places, but follow the compiler messages and it should lead you to the right place.

One of the places that will need updating is getPosts, where you'll need to take the list of posts out of that wrapper object. That should be as simple as this:

|> Task.map (ShowPosts << .posts)

Upvotes: 1

Related Questions