Alan Coromano
Alan Coromano

Reputation: 26008

How to parse a list of Json objects in Haskell?

I have a data class:

data MyData = MyData { a :: Int, b :: String }
instance ToJSON MyData where
  ....

instance FromJSON MyData where
  ....

I can parse a single object from json:

get :: IO (Maybe MyData)
get = do
  res <- getSingleItemHttp
  return $ decode $ responseBody res

How can I get a list of MyData?

get2 :: IO [MyData]
get2 = do
      res <- getManyItemsHttp

      --????
      return $ decode $ responseBody res -- doesn't compile

How would I go about parsing responseBody to List?

Upvotes: 0

Views: 1230

Answers (1)

Random Dev
Random Dev

Reputation: 52280

It should work as it is once you pass in an array (and decode as a list) so you probably just have to change your signature to get2 :: IO (Maybe [MyData]):

{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
module Json where

import GHC.Generics
import Data.Aeson
import Data.Text
import Data.ByteString.Lazy

data MyData = MyData { a :: Int, b :: String }
  deriving (Generic, Show)

instance FromJSON MyData

example :: ByteString
example = "[{ \"a\": 1, \"b\": \"Hello\" }, { \"a\": 2, \"b\": \"World\" }]"

example

λ> decode example :: Maybe [MyData]
Just [MyData {a = 1, b = "Hello"},MyData {a = 2, b = "World"}]

your problem

would be something like this: if you try

get :: [MyData]
get = decode example

the compiler will complain with

Couldn't match expected type [MyData] with actual type Maybe a0

which should give you a big hint.

You can still get your signature with Data.Maybe.maybeToList:

get :: [MyData]
get = Prelude.concat . maybeToList $ decode example

Upvotes: 3

Related Questions