如何自动将 "makeFields" lens 格式的记录转换为 JSON 字段匹配 lenses?

How to automatically convert a record in "makeFields" lens format to JSON with fields matching lenses?

data ArticlePreview = ArticlePreview
  { _articlePreviewName          :: T.Text
  , _articlePreviewPerex         :: T.Text
  , _articlePreviewAuthorName    :: T.Text
  , _articlePreviewAuthorUrl     :: T.Text
  , _articlePreviewDate          :: T.Text
  , _articlePreviewCategoryName  :: T.Text
  , _articlePreviewCategoryUrl   :: T.Text
  , _articlePreviewCommentsCount :: Maybe Integer
  } deriving (Show, Eq, Generic)

makeFields ''ArticlePreview

我试过爱生:

instance ToJSON ArticlePreview
instance FromJSON ArticlePreview

encodeToString :: ToJSON a => a -> String
encodeToString = CL.unpack . encode

输出:

{"_articlePreviewCommentsCount":17,"_articlePreviewAuthorName":"x","_articlePreviewName":"x","_articlePreviewCategoryName":"x","_articlePreviewAuthorUrl":"x","_articlePreviewCategoryUrl":"x","_articlePreviewDate":"x","_articlePreviewPerex":"x"}

期望的输出:

{"commentsCount":17,"authorName":"x","name":"x","categoryName":"x","authorUrl":"x","categoryUrl":"x","date":"x","perex":"x"}

我不坚持Aeson,但它必须是自动的(没有手动定义,例如_articlePreviewCommentsCount映射到commentsCount)。

您可以使用模板 Haskell 从 Data.Aeson.TH 导出 FromJSON/ToJSON,这允许进行一些修改:

import Data.Aeson.TH
import Data.Char

deriveJSON
  defaultOptions {fieldLabelModifier = (_head %~ toLower) . drop 15}
  ''ArticlePreview

t :: ArticlePreview
t = ArticlePreview "" "" "" "" "" "" "" (Just 12)

然后你得到:

GHCI> encode t
"{\"name\":\"\",\"perex\":\"\",\"authorName\":\"\",\"authorUrl\":\"\",\"date\":\"\",\"categoryName\":\"\",\"categoryUrl\":\"\",\"commentsCount\":12}"