Haskell beginner here. I want to pass a "type" parameter with JSON, and have it parse into a native Haskell type using read. The following works:
data CreatureType = Bot | Player deriving (Generic, Typeable, Show, Read)
data Creature = Creature CreatureType deriving (Typeable, Show)
instance FromJSON Creature where
parseJSON (A.Object v) = Creature <$> read <$> (v .: "type")
parseJSON _ = mzero
I want to change it to work with readMay
, so that it doesn't crash if read fails. I keep getting stuck. parseJSON needs to return mzero
if readMay
returns Nothing
.
Main Question: How can I get this function to use readMay
to return mzero
on a failure with read?
Here's what I've tried:
instance FromJSON Creature where
parseJSON (A.Object v) = do
let t = (v .: "type") :: Parser String
mt = readMay <$> t :: Parser (Maybe CreatureType)
-- ??
-- guard -- I can't use this because it wants a Bool, and I only have Parser Bool
-- Creature <$> read <$> mt
parseJSON _ = mzero
mt
is Parser (Maybe CreatureType)
. How can I change what I return if it is Nothing
? I can't use pattern matching, because Data.Aeson
doesn't seem to export a value constructor for Parser. I can't seem to find any methods that will give me the value inside a parser, so, is there a generic haskell method that does it? I've looked at Control.Applicative
and can't find anything. Here are the docs for Data.Aeson
. http://hackage.haskell.org/packages/archive/aeson/0.5.0.0/doc/html/Data-Aeson.html