将JSON转换回Haskell中的Data

时间:2016-07-29 10:47:46

标签: json haskell

我有以下Haskell来调用我的WCF服务:

{-# 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:由于Janos 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 个答案:

答案 0 :(得分: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

相同