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

IssueとのようなものをVersion同じ階層の別のファイルに入れることで、これをプロトコルバッファーで解決します。

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 に答える