首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与conduit sinkParser相结合的伊森deriveJSON

与conduit sinkParser相结合的伊森deriveJSON
EN

Stack Overflow用户
提问于 2012-11-08 22:29:39
回答 1查看 941关注 0票数 4

继续我对conduit和aeson的探索,在这个来自Yesod book的(稍微修改过的)代码片段中,我将如何使用我自己的数据类型而不是Value

代码语言:javascript
复制
{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
import Network.Wai (Response, responseLBS, Application, requestBody)
import Network.HTTP.Types (status200, status400)
import Network.Wai.Handler.Warp (run)
import Data.Aeson.Parser (json)
import Data.Conduit.Attoparsec (sinkParser)
import Control.Monad.IO.Class (liftIO)
import Data.Aeson (Value(..), encode, object, (.=))
import Control.Exception (SomeException)
import Data.ByteString (ByteString)
import Data.Conduit (ResourceT, ($$))
import Control.Exception.Lifted (handle)

import qualified Data.HashMap.Strict as M
import Data.Aeson.TH (deriveJSON)

-- I ADDED THIS

data JSONRequest = JSONRequest {
    command :: ByteString,
    params :: M.HashMap ByteString ByteString
}

deriveJSON id ''JSONRequest

-- END OF WHAT I ADDED

main :: IO ()
main = run 3000 app

app :: Application
app req = handle invalidJson $ do
    value <- requestBody req $$ sinkParser json
    newValue <- liftIO $ dispatch value
    return $ responseLBS
        status200
        [("Content-Type", "application/json")]
        $ encode newValue

invalidJson :: SomeException -> ResourceT IO Response
invalidJson ex = return $ responseLBS
    status400
    [("Content-Type", "application/json")]
    $ encode $ object
        [ ("message" .= show ex)
        ]

-- Application-specific logic would go here.
dispatch :: Value -> IO Value
dispatch = return

基本上,我希望将dispatch的类型更改为JSONRequest -> IO JSONRequest。如何告诉解析器使用我自己的fromJSON派生实例?

我试着添加一个类型声明,祈祷json上的多态返回类型,但我意识到它是严格对值的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-09 00:01:25

看看类型,难道你不需要在来自json的结果上fmap你的fromJSON吗?有了适用于dispatch的签名,我们只需要:

代码语言:javascript
复制
-- import Data.Aeson
app :: Application
app req = handle invalidJson $ do
      result <- requestBody req $$ sinkParser (fmap fromJSON json)
      next_result <- liftIO $ dispatch result
      return $ responseLBS status200 [("Content-Type", "application/json")] 
             $ encode next_result   

dispatch :: Result JSONRequest -> IO JSONRequest
dispatch (Error str) = undefined
dispatch (Success jsonreq) = return jsonreq

但可能会写得更清楚一些:

代码语言:javascript
复制
-- import Data.Aeson
-- import qualified Data.Attoparsec as Atto
toRequest ::    Value -> Result JSONRequest
toRequest = fromJSON   -- specialized now to your fromJSON

jsonRequestParser :: Atto.Parser (Result JSONRequest)
jsonRequestParser = fmap toRequest json 

app :: Application
app req = handle invalidJson $ do
      result <- requestBody req $$ sinkParser jsonRequestParser
      next_result <- liftIO $ dispatch result
      return $ responseLBS status200 [("Content-Type", "application/json")]
             $ encode next_result   

dispatch :: Result JSONRequest -> IO JSONRequest
dispatch (Error str) = undefined
dispatch (Success jsonreq) = return jsonreq

我让解析器返回一个Result JSONRequest,所以dispatch也在处理错误情况,这可能意味着你需要以某种方式处理异常?

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13290975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档