I'm trying to parse some blog posts that have tag metadata as semicolon-separated strings, e.g.:
#+title: Some Title
#+date: 2021-02-04
#+keywords: tag1; tag two; tag three
I have a data structure for them, and I just need to get the Aeson parser to split on semicolons. However, it seems it's not as simple as this:
data SrcMeta
= SrcMeta
{ title :: Text,
date :: Text,
tags :: [Text]
}
deriving (Show, Eq, Generic)
instance FromJSON SrcMeta where
parseJSON (Aeson.Object v) = do
title <- v Aeson..: "title"
date <- v Aeson..: "date"
tags <- T.splitOn ";" $ v Aeson..: "keywords"
return SrcMeta { title = title, date = date, tags = tags }
The type mismatch is that T.splitOn
needs a Text
, and .:
returns a Parser
. Am I thinking about this wrong? What's the best way of parsing a semicolon-separated string into a [Text]
?
You can first retrieve the Text
and then split it, like:
instance FromJSON SrcMeta where
parseJSON (Aeson.Object v) = do
title <- v Aeson..: "title"
date <- v Aeson..: "date"
tags <- v Aeson..: "keywords"
return SrcMeta { title = title, date = date, tags = T.splitOn ";" tags }
another option is working with a functor mapping (<$>) :: Functor f => (a -> b) -> f a -> f b
:
instance FromJSON SrcMeta where
parseJSON (Aeson.Object v) = do
title <- v Aeson..: "title"
date <- v Aeson..: "date"
tags <- T.splitOn ";" <$> (v Aeson..: "keywords")
return SrcMeta { title = title, date = date, tags = tags }