2014-11-06 2 views
2

Я пишу службу JSON для JIRA, и я столкнулся с требованием, которое противоречит пространству имен Haskell. У меня есть эта записьКак у вас есть две записи с одинаковыми именами полей?

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

Это продиктовано тем, что JIRA хочет, к сожалению, она хочет того же поля для другого объекта.

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

Я вижу несколько вариантов:

  1. Может быть, я могу обойти компилятор жалуется с шаблоном Haskell, но как?
  2. Я мог просто не иметь запись Репортера и изменить поле репортера с отдельной службой после создания билета. Что я знаю, как это сделать, но это лучший способ?
  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' функцию. –

ответ

7

Самый простой способ - включить расширение -XDisambiguateRecordFields.

+0

Это трюк, я просто держу их в отдельных модулях. –

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\"}" 
Смежные вопросы