2014-11-06 61 views
2

我正在爲JIRA編寫JSON服務,並且遇到了與Haskell命名空間衝突的需求。 我有這樣的記錄你怎麼能有兩個相同的字段名稱的記錄?

data Assignee = Assignee {name :: Text} deriving Generic 
instance ToJSON Assignee 

這是由什麼JIRA希望,不幸的是它要對不同的對象相同的字段決定。

data Reporter = Reporter {name :: Text} deriving Generic 
instance ToJSON Reporter 

我看到幾個選項:

  1. 也許我可以繞過編譯器與模板哈斯克爾抱怨,但如何?
  2. 我可以根本沒有Reporter記錄,並且在創建票證後使用單獨的服務更改記者字段。我知道該怎麼做,但這是最好的方法嗎?
  3. 手工創建JSON對象,但我形成從這個紀錄:

    data Fields = Fields 
          { project  :: HashMap Key Project 
          , summary  :: Text 
          , issuetype :: HashMap Name Task 
          , versions :: [HashMap Name Text] 
          , description :: Text 
          , assignee :: Assignee 
          } deriving (Generic) 
    

使這一手的想法使我威金斯。如果我必須,我會的。

所以,現在我的問題是,如果沒有其他更好的方法比我提出的方法,哪個是最好的行動方案?

+1

也許你可以在不同的模塊,把它們寫和不導入'name'功能。 – 2014-11-06 23:16:32

回答

7

最簡單的方法是啓用-XDisambiguateRecordFields擴展名。

+0

這樣做,我只是把它們放在單獨的模塊中。 – 2014-11-07 00:45:19

6

如果DisambiguateRecordFields和/或保持獨立模塊中的記錄適用於您,那很好。

如果沒有,那麼一個共同的方式來解決這個問題,在某種程度上前綴記錄字段標籤,消除歧義:

data Assignee = Assignee {assigneeName :: Text} deriving Generic 
data Reporter = Reporter {reporterName :: Text} deriving Generic 

你仍然可以使用GHC泛型導出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\"}" 
相關問題