在Haskell中从Web服务器解析JSON

时间:2014-01-05 06:18:21

标签: json haskell

假设我要解析http://reddit.com/r/haskell.json

中的JSON
main = do
  rsp <- simpleHTTP (getRequest "http://www.reddit.com/r/haskell.json")
  str <- fmap (takeWhile isAscii) (getResponseBody rsp)

我现在有一个准备解析的字符串。但是,Aeson的decode函数具有以下类型签名:

decode :: FromJSON a => 
  bytestring-0.10.0.2:Data.ByteString.Lazy.Internal.ByteString -> Maybe a

如何解码该字符串中的JSON?或者有更好的方法来解码GET请求吗?

1 个答案:

答案 0 :(得分:4)

simpleHTTP是多态的。包含的响应正文可以是严格ByteString,懒惰ByteStringString中的任何一种。它选择其中一个以匹配传递给它的Request ty值。遗憾的是,HTTP是一个旧的库并且维护得很差 - 它最低限度地添加了处理这三种类型所必需的多态性,但并不是它可以使图书馆友好使用的所有地方。例如,使用getRequest强制响应为String,从而使simpleHTTP中的多态性无效。

以下是使用HTTP抓取该网址内容并使用aeson对其进行解码的最小工作示例。

import Network.URI
import Network.HTTP
import Data.Aeson

-- There's absolutely no reason that this function shouldn't be in HTTP.
-- It's just as unsafe and terrible as getRequest is. In fact, this is a
-- strictly more general type than getRequest has, so there's no reason
-- it shouldn't just replace it.
getRequest_ :: HStream ty => String -> Request ty
getRequest_ s = let Just u = parseURI s in defaultGETRequest_ u

main :: IO ()
main = do
    rsp <- simpleHTTP $ getRequest_ "http://www.reddit.com/r/haskell.json"
    body <- getResponseBody rsp
    print (decode $ body :: Maybe Value)

请注意,使用decode最终确定了simpleHTTP的多态类型。只是在这个版本中,它与getRequest关于代码中的类型的说法并不矛盾。