First, find a safe read function. I had to hoogle it.
Second, you have to use more than just applicative to get choice. In the below, I used readMay
for the safe read and made a helper function to extract the fields while applying the Read instance.
{-# LANGUAGE OverloadedStrings, NoMonomorphismRestriction #-}
import Safe
import Data.Aeson
import Data.Aeson.Types (Parser)
import Data.Text as T
import Data.Word
import Control.Applicative
import Control.Monad
data Quote = Quote Text Double Double Double Double Word64
instance FromJSON Quote where
parseJSON (Object o) = do
let readField :: (Read a) => T.Text -> Parser a
readField f = do
v <- o .: f
case readMay (T.unpack v) of
Nothing -> fail $ "Bad Field: " ++ T.unpack f
Just r -> return r
Quote <$> o .: "Date"
<*> readField "Open"
<*> readField "Close"
<*> readField "Low"
<*> readField "High"
<*> readField "Volume"
parseJSON _ = mzero