My type and corresponding implementation of FromJSON as below.
nonEmptyturns a Listinto Maybe NonEmpty, and I'm trying to correctly deal with the case when it is Listreally empty, and I have to interrupt the parsing. This parsing is actually done internally parseJsonBody, which means I don't want error "foo"to exit it, but I want to return mzero(or something else will do the trick mzero- the only thing I've come across so far), so the handler correctly returns 400 instead of crashing with 500.
The approach compiled below, but as far as I can tell, is pretty much equal to erroror some other form of exception throwing inside parseJSON. If I return mzerohowever (for example, using <*> mzeroinstead of this line), this is not as good 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 match the templates with the result fmap NE.nonEmpty (o .: "responses"), but I can’t figure out which template will be there: doesn't it look like Parser has any constructors?
source
share