2012-12-12 4 views
6

私はJIRAJSONオブジェクトをマーシャルするためにdataレコードを書いています。問題は、複数のオブジェクトが名前と値のペアで同じラベルを持つことです。 (カールから返され、フォーマット)ハスケルネームスペースに対処するには?

{"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 
        } 
      } 
      ] 

私は問題の対応Haskellの私が取得dataレコードを構築する場合:たとえば

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' と '自己' は衝突しますが。レコード内の名前を変更し、手動で作成したFromJSONインスタンスで修正するだけで、この問題を解決することができました。 代替ソリューションをご利用いただけます。

答えて

10

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

ハスケルは名前空間を制御するために別個のモジュールしか使用しないので、これは正統的な解決法です。

はるかに手の込んだ:利用型クラス利用可能名を定義するには:

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 .... 

編集:以下のコメントは、より詳細な助言を与えることを思い出させます。自分自身を解決策のように使ってはいけません。別々のモジュールのパスを保証することができます。

PS:おそらく、あなたのフィールドにlensライブラリを使用することができます!

+7

注:たとえば、次のデータ型は、フィールドの矛盾せずに自分の価値を表現することができます。しかし、相互運用性のために非Haskellコードの構造を一致させようとするとき、他の側が過負荷関数やサブタイプ階層に大きく依存している場合、より良いアプローチはないかもしれません。 –

+0

私はあなたが別々のファイルを推奨した部分をupvotingしています。型クラスは、ユーザーが型を推論するのが非常に難しく、間違った型に誤って失敗したり、間違ったことをするため、型の悪い名前解決ソリューションを作成します。 –

3

別の代替レコードを含む単一のデータ型を使用することもできます。それはきれいな、よく構造化Haskellのコードを書くことになるとHasFoobar`スタイル型クラスは、ほとんど常にひどいアイデアです `こと

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 
          } 
       } 
       ] 
    } 
+0

上記は、すべての 'id'が同じ型(' Int')で、すべて 'self'が同じ型(' String')である場合にのみ動作することに注意してください。 –

関連する問題