6

我正在写一个data记录来编组一个JIRA JSON对象。问题是,多个对象具有相同的名称/值对标签。例如 :

(从 curl 返回并格式化)

{"expand":"schema,names"
,"startAt":0
,"maxResults":2
,"total":74
,"issues":[
           {"expand":"editmeta,renderedFields,transitions,changelog,operations"
           ,"id":"183614"
           ,"self":"https://10.64.16.44/rest/api/latest/issue/183614"
           ,"key":"BNAP-339"
           ,"fields":{"versions":[
                                  {"self":"https://10.64.16.44/rest/api/2/version/28240"  
                                  ,"id":"28240"
                                  ,"name":"2012-12-07"
                                  ,"archived":false
                                  ,"released":false
                                  }
                                 ]
                     ,"status":{"self":"https://10.64.16.44/rest/api/2/status/1"
                               ,"description":"The issue is open and ready for the assignee to start work on it."
                               ,"iconUrl":"https://10.64.16.44/images/icons/status_open.gif"
                               ,"name":"Open"
                               ,"id":"1"
                               }
                     ,"description":"Do Re Mi Fa"
                     ,"resolution":null
                     }
           }
          ]

当我构建有问题的相应 Haskelldata记录时,我得到:

data Issue = Issue {expand :: String
                   ,id :: String
                   ,self :: String
                   ,key :: String
                   ,fields :: Fields
                   } deriving Generic


data Version = Version {self :: String
                       ,id :: String
                       ,name :: String
                       ,archived :: Bool
                       ,released :: Bool
                       } deriving Generic

'id' 和 'self' 会发生冲突。我突然想到,我可以通过更改记录中的名称并使用手动创建的FromJSON实例来修复它来解决这个问题。欢迎任何替代解决方案。

4

2 回答 2

10

我在协议缓冲区中解决了这个问题,方法是将之类的东西放在同一层次结构中的单独文件中IssueVersion

Haskell 只使用单独的模块来控制命名空间,所以这是正统的解决方案。

更高级:使用类型类来定义可用的名称:

class Has'self a b | a -> bwhere
   get'self :: a -> b
   set'self :: b -> a -> b

instance Has'self Issue String where ...
instance Has'self Version String where ....

编辑:下面的评论提醒我提供更详细的建议。不要使用 Has'self 之类的解决方案——那些走这条路的人报告它变得丑陋。我可以保证单独模块的路径。

PS:也许您可以将镜头库用于您的领域!

于 2012-12-12T21:32:58.973 回答
3

另一个可行的替代方法是使用包含不同记录的单一数据类型。例如,以下数据类型能够表示您的值而不会发生字段冲突:

import Prelude hiding (id)

data JIRA = JIRA
  { expand :: String
  , startAt :: Int
  , maxResults :: Int
  , total :: Int
  , issues :: [JIRA]
  } | Issue 
  { expand :: String
  , id :: Int
  , self :: String
  , key :: String
  , fields :: JIRA
  } | Field
  { versions :: [JIRA]
  , status :: JIRA
  , description :: String
  , resolution :: Maybe String
  } | Version
  { self :: String
  , id :: Int
  , name :: String
  , archived :: Bool
  , released :: Bool
  } | Status
  { self :: String
  , description :: String
  , iconUrl :: String
  , name :: String
  , id :: Int
  }


yourExample = JIRA
  { expand = "schema, names"
  , startAt = 0
  , maxResults = 2
  , total = 74
  , issues = [ Issue
               { expand = "editmeta, etc..."
               , id = 12345
               , self = "https://xyz"
               , key = "BLAH"
               , fields = Field
                          { versions = [ Version
                                          { self = "https://foobar"
                                          , id = 1234
                                          , name = "quux"
                                          , archived = False
                                          , released = False
                                          }
                                       ]
                          , status = Status
                                     { self = "https://etc"
                                     , description = "issue"
                                     , iconUrl = "https://iconurl"
                                     , name = "open"
                                     , id = 1
                                     }
                          , description = "another description"
                          , resolution = Nothing
                          }
                 }
               ]
  }
于 2012-12-13T02:44:27.807 回答