First, look at the type of
((o .: "doc") >>=
(.: "sourceResource") >>=
(.: "subject")) :: FromJSON b => Parser b
We can get out of it anything that's an instance of FromJSON
. Now, clearly, this can work for Text
or [Text]
individually, but your problem is that you want to get either Text
or [Text]
. Fortunately, it should be fairly easy to deal with this. Rather than letting it decode it for you further, just get a Value
out of it. Once you've got a Value
, you could decode it as a Text
and put it in a SubjectText
:
SubjectText <$> parseJSON val :: Parser Row
Or as a [Text]
and put it in a SubjectList
:
SubjectList <$> parseJSON val :: Parser Row
But wait, either one of these will do, and they have the same output type. Notice that Parser
is an instance of Alternative
, which lets us say exactly that (“either one will do”). Thus,
(SubjectList <$> parseJSON val) <|> (SubjectText <$> parseJSON val) :: Parser Row
Ta-da! (Actually, it wasn't necessary to pull it out as a Value
; we could have instead embedded that long ((o .: "doc") >>= (.: "sourceResource") >>= (.: "subject"))
chain into each subexpression. But that's ugly.)