Haskellでjsonを楽に扱う方法
Haskellから、twitter APIなどJSONを使いたい場面でどう書くかという話。
よくある書き方
data Tweet=Tweet {text :: String ,user :: User ,id :: Int , ... } data User=User {screen_name :: String ,name :: String ,id :: Int , ... } jsonToTweet :: JSValue -> Maybe Tweet jsonToTweet v=do arr<-fromJSObject v text<-lookup arr "text" user<-jsonToUser =<< lookup arr "user" -- extract some more entries return Tweet{text=text,user=user,...} jsonToUser :: JSValue -> Maybe User ... fromJSObject :: JSValue -> Maybe [(String,JSValue)] ...
こういうコードを書くのは面倒で、バグも入り易い。
解決法
実は、jsonライブラリにはText.JSON.Genericがあって、Dataのインスタンスならば自動でencode/decodeできる。
class Typeable a => Data a
なのでTypeableのインスタンスである必要もあるけど、GHC拡張のDeriveDataTypeableを使えばderiving(Typeable,Data)できるようになる。
data Tweet=Tweet{...} deriving(Typeable,Data) data User=User{...} deriving(Typeable,Data) -- fromJS_generic :: Data a => JSValue -> Result a を呼ぶだけ!