Home > Back-end >  How can I manipulate an Aeson value?
How can I manipulate an Aeson value?

Time:12-18

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]?

CodePudding user response:

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 }
  • Related