2014-01-05 99 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