2016-07-29 43 views
0

我有以下哈斯克尔打电话给我的WCF服务:转换JSON回的数据在Haskell

{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE DeriveGeneriC#-} 

module Main where 

import Data.Aeson 
import Data.Dynamic 
import Data.Aeson.Lens 
import Data.ByteString.Lazy as BS 
import GHC.Generics 
import Network.Wreq 
import Control.Lens 

data Point = Point { x :: Int, y :: Int } deriving (Generic, Show) 
instance ToJSON Point 
instance FromJSON Point 

data Rectangle = Rectangle { width :: Int, height :: Int, point :: Point } deriving (Generic, Show) 
instance ToJSON Rectangle 
instance FromJSON Rectangle 

main = do   
    let p = Point 1 2 
    let r = Rectangle 10 20 p 
    let url = "http://localhost:8000/Rectangle" 
    let opts = defaults & header "Content-Type" .~ ["application/json"] 
    r <- postWith opts url (encode r)  
    let returnData = r ^? responseBody 
    case (decode returnData) of 
     Nothing  -> BS.putStrLn "Error decoding JSON" 
     Just json  -> BS.putStrLn $ show $ decode json 

在这种情况下的输出是:

Just "{\"height\":20,\"point\":{\"x\":1,\"y\":2},\"width\":10}" 

我已经与fromJSON试了一下:

print $ fromJSON returnData 

,并得到这个错误:

Couldn't match expected type `Value' 
       with actual type `Maybe 
            bytestring-0.10.6.0:Data.ByteString.Lazy.Internal.ByteString' 
    In the first argument of `fromJSON', namely `returnData' 
    In the second argument of `($)', namely `fromJSON returnData' 
Failed, modules loaded: none. 

我的问题是现在如何将这个JSON字符串转换回类型为“Rectangle”的对象?

编辑1:我改变了我的代码由于亚诺什Potecki的答案,现在收到以下错误:

Couldn't match type `[Char]' with `ByteString' 
    Expected type: ByteString 
     Actual type: String 
    In the second argument of `($)', namely `show $ decode json' 
    In the expression: BS.putStrLn $ show $ decode json 
    In a case alternative: 
     Just json -> BS.putStrLn $ show $ decode json 
Failed, modules loaded: none. 

编辑2:我改成了:

main = do   
    let point = Point 1 2 
    let rectangle = Rectangle 10 20 point 
    let url = "http://localhost:8000/Rectangle/Move/100,200" 
    let opts = defaults & header "Content-Type" .~ ["application/json"] 
    r <- postWith opts url (encode rectangle)  
    let returnData = (r ^? responseBody) >>= decode 
    case returnData of 
    Nothing  -> BS.putStrLn "Error decoding JSON" 
    Just json  -> BS.putStrLn json 

和现在我得到:

No instance for (FromJSON ByteString) 
     arising from a use of `decode' 
    In the second argument of `(>>=)', namely `decode' 
    In the expression: (r ^? responseBody) >>= decode 
    In an equation for `returnData': 
     returnData = (r ^? responseBody) >>= decode 
+1

的'fromJSON'函数不解析JSON,它只是将解析的JSON转换成其他Haskell数据结构。你想要'解码',而不是。然而,'returnData'不是'ByteString',它是一个'Maybe ByteString',所以你必须使用模式匹配,使用>> >>或其他工具来处理'returnData'为'Nothing的可能性'。在这个例子中,print(decode = << returnData)'应该做你想要的。 –

回答

3

工作液

r' <- asJSON =<< postWith opts url (encode rectangle) :: IO Res 
case r' of 
    Nothing  -> print "Error decoding JSON" 
    Just x   -> print x 

出于性能方面我建议你添加以下到您的instance ToJSON

instance ToJSON Point where 
     toEncoding = genericToEncoding defaultOptions 

与同为Rectangle

+0

我试过你的解决方案,现在我得到了另一个错误,请参阅我的编辑1上面 – ManzMoody

+0

对不起,'解码'当然要很多 –

+0

我改变了它,现在得到:'无法匹配预期的类型'ByteString' 与实际类型'也许ByteString' 在'decode'的第一个参数中,即'returnData' 在表达式中:(decode returnData)' – ManzMoody