タイムラインのJSONデータを解析してみる(Text.JSON)
API利用は前回できましたので、次はタイムラインの取得を。
とは言ったものの、CUIなので見栄えはしませんが……
自動更新もつけてません。
自分のアカウントのタイムラインを取得するには、home_timelineを使えばOK。
パラメータはいりませんが、いろいろとオプションで付けることができます。
何もパラメータを付けずにリクエストすると、最新20件のツイートを取得します。
このとき、データの形式は色々と選ぶことができるのですが、
今回はJSON形式を使ってみました。
HaskellにはJSON解析ライブラリがあります。
cabal install JSONでText.JSONモジュールを使います。
decode :: JSON a => String -> Result a
でJSONデータの文字列をパースしてくれます。
取得データの形式は次のようになってました。
・(home_timelineで取得できるデータ) = JSArray [(tweet)] (各tweetが最新のものから順に入っている)
・(tweet) = JSObject JSValue (各ツイートのデータ)
・ツイートのデータにはさらに"user"フィールドというJSObject型の値が存在し、ここにツイートしたアカウントの詳細なデータが入っている
ツイートのデータはかなり多いのでここに書くのは省略……
JSObject型は、fromJSObject関数で連想リストの形に変換できるので、
変換して目的のデータをデータ名で指定して取得する関数、及び取り出したJSValue型から目的の型にあったデータを取得してくる関数を作ることで、
各フィールドの値にアクセスするようにしました。
-- ツイート data Tweet = Tweet { name :: String, -- ユーザ名 screen_name :: String, -- ユーザID retweeted :: Bool, -- リツイートされたか created_at :: String, -- ツイートされた時刻 profile_image_url :: String, -- プロフィール画像 text :: String -- ツイート内容 }
-- オブジェクト名指定で対応するJSONオブジェクトの値を取得
findJSObject :: Monad m => JSObject a -> String -> m a
findJSObject jsobject objectName =
case dropWhile ( (/= objectName) . fst) (fromJSObject jsobject) of
[] -> fail $ "findJSObject: Not_found(\"" ++ objectName ++ "\")"
object:_ -> return . snd $ object
ofJSBool :: Monad m => JSValue -> m Bool
ofJSBool (JSBool b) = return b
ofJSBool _ = fail "ofJSBool: Not JSBool"
ofJSString :: Monad m => JSValue -> m String
ofJSString (JSString str) = return $ fromJSString str
ofJSString _ = fail "ofJSBool: Not JSString"
ofJSObject :: Monad m => JSValue -> m (JSObject JSValue)
ofJSObject (JSObject jsobject) = return jsobject
ofJSObject _ = fail "ofJSBool: Not JSObject"
-- ツイートを取得
getTweet :: Monad m => JSObject JSValue -> m Tweet
getTweet jsobject = do
user <- ofJSObject =<< findJSObject jsobject "user"
name <- ofJSString =<< findJSObject user "name"
screen_name <- ofJSString =<< findJSObject user "screen_name"
retweeted <- ofJSBool =<< findJSObject jsobject "retweeted"
created_at <- ofJSString =<< findJSObject jsobject "created_at"
profile_image_url <- ofJSString =<< findJSObject user "profile_image_url"
text <- ofJSString =<< findJSObject jsobject "text"
return $ Tweet name screen_name retweeted created_at profile_image_url text
それなりに使いやすいインタフェースに出来たかなと思います。
各関数において、不正なデータ型が来たらエラーにするようにしてあります。(ofJSBool, ofJSString, ofJSObject)
で、コードですが、ようやくgithubに上げました。