2

toJSON の定義を書かないようにしています。これは私が遭遇したエラーです:

Datatypes.hs:92:10:
    No instance for (aeson-0.6.0.2:Data.Aeson.Types.Class.GToJSON
                       (GHC.Generics.Rep (HashMap Key Project)))
      arising from a use of `aeson-0.6.0.2:Data.Aeson.Types.Class.$gdmtoJSON'
Possible fix:
  add an instance declaration for
  (aeson-0.6.0.2:Data.Aeson.Types.Class.GToJSON
     (GHC.Generics.Rep (HashMap Key Project)))
In the expression:
  (aeson-0.6.0.2:Data.Aeson.Types.Class.$gdmtoJSON)
In an equation for `toJSON':
    toJSON = (aeson-0.6.0.2:Data.Aeson.Types.Class.$gdmtoJSON)
In the instance declaration for `ToJSON (HashMap Key Project)'

すべての HashMapdata宣言で同様のエラーが発生します。

関連するコードは次のとおりです。情報が不足している場合はお知らせください。

{-# LANGUAGE DeriveGeneric #-}  -- for JTask and Fields ToJSON instances:w!
{-# LANGUAGE DeriveDataTypeable #-} -- This may be needed for HashMaps
{-# LANGUAGE FlexibleInstances #-} -- for the HashMap ToJSON instances
{-# LANGUAGE DefaultSignatures #-}

import Prelude
import Data.ByteString
import GHC.Generics (Generic )
import Data.Data 
import Data.Typeable (Typeable) -- fix HashMap ToJSON instances? maybe
import Data.Aeson
import Data.Aeson.Generic  
import Data.Aeson.Types -- (ToJSON,FromJSON)
import Data.HashMap.Strict (HashMap)

data JTask = JTask {fields :: Fields} deriving (Typeable,Data,Generic)
data Fields = Fields { project :: HashMap Key Project
                     , summary :: ByteString
                     , issuetype :: HashMap Name Task
                     , versions :: [HashMap Name Version]
                     , description :: ByteString
                     } deriving (Typeable,Data,Generic)

data Key = Key deriving (Typeable,Data,Generic)
instance Show Key where
   show Key = "key"

data Name = Name deriving (Typeable,Data,Generic)
instance Show Name where
   show Name = "name"

data Task = Task deriving (Typeable,Data,Generic)

type Version = ByteString -- Placeholder type. Probably using Day for realsies.

data Project = BNAP deriving (Typeable,Data,Generic) -- Fill this out as we go 

instance Generic (HashMap Key Project)
instance Data (HashMap Key Project)
--instance GToJSON (HashMap Key Project)

instance Generic (HashMap Name ByteString)
instance Data (HashMap Name ByteString)

instance Generic (HashMap Name Task)
instance Data (HashMap Name Task)
-- JSON instances
instance ToJSON CreateError
instance ToJSON Fields
instance ToJSON JTask 

instance ToJSON Key
instance ToJSON Name
instance ToJSON Task
instance ToJSON Project

instance ToJSON (HashMap Key Project)
instance ToJSON (HashMap Name Task)
instance ToJSON (HashMap Name ByteString)
-- instance ToJSON Version uncomment when we change Version's type.

はエクスポートされていないData.Aeson.Types.Class.GToJSONため、 のインスタンスを作成できません。Data.Aeson.Types.Class私のオプションは何ですか?手動で何を書く必要がありますか? deriveJSON最良の選択ですか?

更新: 以下の提案を実装しました。これがコードです

createObject :: CreateConf -> ResourceT IO Value
createObject (CreateConf iSummary iDesc dd) = do
   let jfields = Fields {project = singleton Key BNAP
                        ,summary = iSummary
                        ,issuetype = singleton Name Task
                        ,versions = [singleton Name (calcVersion dd)]
                        ,description = iDesc
                        }
return $ toJSON (JTask jfields)

最初のインスタンスはObject fromList [("key",Array (fromList []))])

2 番目のインスタンスの利回りObject fromList [("name",Array (fromList []))]

なぜnameそしてkey空なのですか?

どうすればわかりますか?

を使用する方が簡単でしょうかderiveJSON

更新: NathanHowell の助けのおかげで、より重要な問題が解決されました。これは、単項型の GToJSON インスタンスです。解決策は、単項型の独自のインスタンスを作成することでした。JSON オブジェクトは順不同ですが、それが問題かどうかはわかりません。もしそうなら、フィールドの別の手動 ToJSON インスタンスがそれを修正するようです。

更新: わかりました少しコンテキスト。私はJIRAフロントエンドを書いています。私が言及したのは、将来人々が次のような良いニュースを発見するためにここに来るかもしれないからです: JIRA はオブジェクトの順序を気にしません。

4

1 に答える 1

4

Aeson は のToJSONインスタンスを提供しますHashMap String a。物事を機能させる最も簡単な方法は、HashMapキーを に変換してこのインスタンスを使用することStringsです。定型文に触れるだけで、Generic他のすべてにインスタンスが使用されます。

{-# LANGUAGE DeriveGeneric #-}  -- for JTask and Fields ToJSON instances:w!
{-# LANGUAGE FlexibleInstances #-} -- for the HashMap ToJSON instances
{-# LANGUAGE DefaultSignatures #-}

import Prelude
import Data.ByteString
import GHC.Generics (Generic )
import Data.Aeson
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap

data JTask = JTask {fields :: Fields} deriving (Generic)
data Fields = Fields { project :: HashMap Key Project
                     , summary :: ByteString
                     , issuetype :: HashMap Name Task
                     , versions :: [HashMap Name Version]
                     , description :: ByteString
                     } deriving (Generic)

data Key = Key deriving (Generic)
instance Show Key where
   show Key = "key"

data Name = Name deriving (Generic)
instance Show Name where
   show Name = "name"

data Task = Task deriving (Generic)

type Version = ByteString -- Placeholder type. Probably using Day for realsies.

data Project = BNAP deriving (Generic) -- Fill this out as we go 

instance ToJSON Fields
instance ToJSON JTask 

instance ToJSON Key
instance ToJSON Name
instance ToJSON Task
instance ToJSON Project

mapfst :: (a -> b) -> [(a, v)] -> [(b, v)]
mapfst f = fmap $ \ (k, v) -> (f k, v)

instance ToJSON a => ToJSON (HashMap Key a) where
  toJSON = toJSON . HashMap.fromList . mapfst show . HashMap.toList

instance ToJSON a => ToJSON (HashMap Name a) where
  toJSON = toJSON . HashMap.fromList . mapfst show . HashMap.toList
于 2012-11-13T20:50:44.210 に答える