Aeson和Lens与DeriveGeneric和makeLenses - 名称不对齐

时间:2015-01-24 08:58:03

标签: json haskell lens aeson

我们说我有一个类型Person

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.

显然,我可以从data定义中删除下划线,但是makeLenses无法导出所需的getter和setter。

理想情况下,我希望能够做的就是这样

let person = decode blob
let name = person ^. firstName

即。我希望能够派生镜头和JSON实例,所有字段名称都正确地排列在JSON-REST Api中消耗的值,而不必编写太多样板文件。

这似乎是一件很直接的事情,我觉得我错过了一些明显的东西?

1 个答案:

答案 0 :(得分:10)

lensaeson都具有允许自定义处理字段和构造函数名称的函数。由于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,
    _lastName  :: Text,
    _age       :: Int
} deriving (Show, 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}
-}

对于lens,相应的可配置函数为makeLensesWith