2014-01-05 49 views
1

比方说,我想从http://reddit.com/r/haskell.jsonJSON解析从Web服务器在Haskell

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

解析JSON我现在已经准备好要解析的字符串。然而,埃宋的decode功能具有以下类型签名:

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

我怎样才能从字符串解码JSON?还是有更好的方法来解码GET请求?

回答

4

simpleHTTP是多态的。包含的响应主体可以是严格的ByteString,惰性ByteStringString中的任意一种。它会选择其中的一个匹配传递给它的值Request ty。不幸的是,HTTP是一个古老的图书馆,维护得不好 - 它最低限度地增加了与这三种类型一起工作所必需的多态性,但并非处处都可以使图书馆友好使用。例如,使用getRequest强制响应为String,取消simpleHTTP中的多态性。

下面是一个最简单的工作示例,它抓取该URL的内容,并使用HTTPaeson进行解码。

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对代码中的类型所说的话。

+0

它确实是'HTTP'包中的'simpleHTTP'。我怎样才能告诉它使用正确的'ByteString',这样我就可以将它提供给'decode'函数? – BinRoot

+0

@Nick只需将它提供给'decode'函数即可。这就是确保它是正确的类型所需要的。这是整个类型推断的要点。 – Carl

+0

得到'rsp'之后,我尝试了'sb < - getResponseBody rsp'然后'decode sb',但是由于它期望'Data.ByteString.Lazy.Internal.ByteString'而导致类型错误失败, Char]' – BinRoot