0

I am trying to convert a JSON String into an ADT

This is my ADT:

data UserList = UserList
  { userListUsers :: [UserId] }

This is my FromJSON instance for UserList:

instance FromJSON UserList where
  parseJSON (Object o) = UserList
    <$> ((o .: "relationships") >>= (.: "users") >>= (mapM (.: "id")))

And finally this is my JSON String:

{
  "relationships": { 
    "users": [
      { "type": "User","id": "8" }
    ]
  }
}

My Yesod server is giving 400 Bad Request, without any further help, I think I may not be converting the users array correctly

FtheBuilder
  • 1,410
  • 12
  • 19

2 Answers2

3

Update

Your parser is fine as you can test with the code below. Your implementation is the same as the one I wrote with do-notation.

Original Answer

This should work:

{-# LANGUAGE OverloadedStrings #-}

import Data.Aeson
import Data.Stringable
import Control.Monad

type UserId = String

data UserList = UserList
  { userListUsers :: [UserId] }
  deriving (Show)

instance FromJSON UserList where
  parseJSON (Object o) = 
    do  r <- o .: "relationships"
        u <- r .: "users"
        idents <- forM u $ \x -> x .: "id"
        return $ UserList idents

test = do
  contents <- readFile "in"
  let e = eitherDecode (toLazyByteString contents) :: Either String UserList
  print e
ErikR
  • 51,541
  • 9
  • 73
  • 124
1

I forgot to use fromPathPiece, I changed to do-notation to make it prettier:

instance FromJSON UserList where
  parseJSON (Object o) = do  
    r <- o .: "relationships"
    u <- r .: "users"
    ids <- forM u $ \x -> do
      id <- x .: "id"
      return $ fromJust . fromPathPiece $ id
    return $ UserList ids
FtheBuilder
  • 1,410
  • 12
  • 19