My type and correponding FromJSON implementation as listed below.
The nonEmpty
turns a List
into a Maybe NonEmpty
and I'm trying to correctly deal with the case where the List
is indeed empty and I have to abort the parsing. This parsing is actually done inside of parseJsonBody
, which means I don't want to error "foo"
my way out of it, but I want to return mzero
(or whatever else will do the trick, mzero
is the only thing I've stumbled upon so far) so that the handler correctly returns a 400 instead of crashing with a 500.
The approach below compiles, but as far as I can tell is pretty much equals to error
or some other form of exception throwing inside of the parseJSON. If I return mzero
however (e.g. with <*> mzero
instead of that line), it fails nicely as intended.
import qualified Data.List.NonEmpty as NE
data GSAnswer = GSAnswer { gsAnswerQuestionId :: Int
, gsAnswerResponses :: NE.NonEmpty GSResponse
} deriving (Show, Eq)
instance FromJSON GSAnswer where
parseJSON (Object o) =
GSAnswer <$> o .: "question-id"
-- how do I return mzero here based on NE.nonEmpty?
-- this will throw an exception right now on an empty list
<*> fmap (fromMaybe (fail "foo") . NE.nonEmpty) (o .: "responses")
parseJSON _ = mzero
One option would be to somehow pattern match on the result of fmap NE.nonEmpty (o .: "responses")
, but I can't quite figure out what the pattern would be there: doesn't look like Parser has any constructors?