假设我有一个类型的人
- import GHC.Generics
- import Data.Text
- import Data.Aeson
- import Control.Lens
- data Person = Person {
- _firstName :: Text,_lastName :: Text,_age :: Int
- } deriving (Show,Generic)
我想自动为它导出镜头和JSON类型类
- makeLenses ''Person
- instance FromJSON Person
- instance ToJSON Person
这可以正常工作,但是DeriveGeneric将我的字段名称视为具有下划线并且期望我的JSON相应地格式化.
- { "_firstName": "James" ... etc} -- The underscore doesn't belong here.
显然我可以从数据定义本身中删除下划线,但是makeLenses将无法派生所需的getter和setter.
理想情况下,我希望能够做到的是这样的事情
- let person = decode blob
- let name = person ^. firstName
即我希望能够导出镜头和JSON实例,所有字段名称都正确排列在我正在消耗的JSON-REST Api中的值,而无需编写太多样板文件.
这似乎是一件很直接的事情,我觉得我错过了一些明显的东西?
解决方法
镜头和aeson都具有允许自定义处理字段和构造函数名称的功能.由于aeson的默认设置不是您想要的,如果您希望镜头名称与JSON字段名称相同,则无论如何都不会工作,让我们更改aeson配置:
- {-# LANGUAGE DeriveGeneric #-}
- {-# LANGUAGE TemplateHaskell #-}
- import GHC.Generics
- import Data.Text hiding (drop)
- import Data.Aeson
- import Data.Aeson.TH
- import Data.Aeson.Types
- import Control.Lens
- data Person = Person {
- _firstName :: Text,Generic)
- makeLenses ''Person
- deriveJSON defaultOptions{fieldLabelModifier = drop 1} ''Person
- {- alternative Generic version
- instance FromJSON Person where
- parseJSON = genericParseJSON defaultOptions{fieldLabelModifier = drop 1}
- instance ToJSON Person where
- toJSON = genericToJSON defaultOptions{fieldLabelModifier = drop 1}
- -}
对于镜头,相应的可配置功能为makeLensesWith
.