我正在为JIRA编写JSON服务,并且我遇到了与Haskell命名空间冲突的要求。 我有这个记录
data Assignee = Assignee {name :: Text} deriving Generic
instance ToJSON Assignee
这是由JIRA想要的,不幸的是它想要一个不同的对象使用相同的字段。
data Reporter = Reporter {name :: Text} deriving Generic
instance ToJSON Reporter
我看到了几个选项:
手动创建JSON对象,但我从此记录中创建它:
data Fields = Fields
{ project :: HashMap Key Project
, summary :: Text
, issuetype :: HashMap Name Task
, versions :: [HashMap Name Text]
, description :: Text
, assignee :: Assignee
} deriving (Generic)
手工制作这个想法给了我一些感觉。如果我必须的话。
所以,我现在的问题是,如果除了我提出的方法之外没有其他更好的方式,哪一项是最好的行动方案?
答案 0 :(得分:7)
最直接的方法是启用-XDisambiguateRecordFields
扩展程序。
答案 1 :(得分:6)
如果DisambiguateRecordFields
和/或将记录保存在单独的模块中,那就非常适合。
如果没有,那么解决此问题的常用方法是以某种方式为记录字段标签添加前缀,以消除歧义:
data Assignee = Assignee {assigneeName :: Text} deriving Generic
data Reporter = Reporter {reporterName :: Text} deriving Generic
您仍然可以使用GHC Generics来派生JSON转换函数,但您必须对其进行配置以便更改字段标签,例如:
stripPrefix :: Eq a => [a] -> [a] -> [a]
stripPrefix p x = case splitAt (length p) x of
(y, z)
| y == p -> z
| otherwise -> x
lower :: String -> String
lower [] = []
lower (x : xs) = toLower x : xs
stripPrefixOptions :: String -> Options
stripPrefixOptions p = defaultOptions {
fieldLabelModifier = lower . stripPrefix p
}
然后你可以说:
data Assignee = Assignee {assigneeName :: Text} deriving Generic
instance ToJSON Assignee where
toJSON = genericToJSON (stripPrefixOptions "assignee")
data Reporter = Reporter {reporterName :: Text} deriving Generic
instance ToJSON Reporter where
toJSON = genericToJSON (stripPrefixOptions "reporter")
在GHCi中进行测试:
GHCi> > encode (Assignee { assigneeName = "foo" })
"{\"name\":\"foo\"}"