是否需要进行aeson解码所需的签名?

时间:2014-06-18 20:10:00

标签: haskell aeson

我正在编写一个小程序来解析TCP连接中的JSON,但我遇到了错误:

Main.hs:43:22:
    No instance for (FromJSON t0) arising from a use of `decode'
    The type variable `t0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there is a potential instance available:
      instance FromJSON LogIn -- Defined at Main.hs:21:10
    In the expression: decode lazyLine
    In a pattern binding: Just login = decode lazyLine
    In the expression:
      do { line <- BS.hGetLine handle;
           let lazyLine = BL.fromChunks ...;
           let Just login = decode lazyLine;
           hPutStrLn handle ".";
           .... }

我不知道要添加到instance FromJSON LogIn的签名。

代码是:

{-# LANGUAGE DeriveGeneric #-}

module Main(main) where

import Network (listenOn, withSocketsDo, accept, PortID(..), Socket)
import System (getArgs)
import System.IO (hSetBuffering, hPutStrLn, BufferMode(..), Handle)
import Control.Concurrent (forkIO)
import qualified Data.ByteString as BS

import Data.Text
import Data.Aeson
import GHC.Generics
import qualified Data.ByteString.Lazy as BL

data LogIn = LogIn
  { username :: String
  , password :: String
  } deriving (Show, Generic)

instance FromJSON LogIn

main :: IO ()
main = withSocketsDo $ do
    sock <- listenOn $ PortNumber 3333
    putStrLn $ "Listening on " ++ "3333"
    sockHandler sock


sockHandler :: Socket -> IO ()
sockHandler sock = do
    (handle, _, _) <- accept sock
    hSetBuffering handle NoBuffering
    forkIO $ commandProcessor handle
    sockHandler sock


commandProcessor :: Handle -> IO ()
commandProcessor handle = do
    line <- BS.hGetLine handle
    let lazyLine = BL.fromChunks [line]
    let Just login = decode lazyLine
    hPutStrLn handle "." --(show login)
    commandProcessor handle

2 个答案:

答案 0 :(得分:5)

这将编译:

commandProcessor :: Handle -> IO ()
commandProcessor handle = do
    line <- BS.hGetLine handle
    let lazyLine = BL.fromChunks [line]
    let Just login = decode lazyLine :: Maybe LogIn
    hPutStrLn handle "." --(show login)
    commandProcessor handle

基本上,您需要告诉aeson解码您要将JSON字符串解码为的内容。

let Just login = decode lazyLine :: Maybe LogIn

答案 1 :(得分:1)

如果您想让Aeson为您生成实例,请确保在编译中打开扩展DeriveGenerics

您需要在行

中添加注释

更改

let Just login = decode lazyLine 

let Just login = decode lazyLine :: Maybe LogIn

否则,您可以手动编写实例。

您需要提供FromJSON LogIn的类型类实例,其中parseJSON已实现

喜欢:

http://hackage.haskell.org/package/aeson-0.6.1.0/docs/Data-Aeson.html#t:FromJSON

{-# LANGUAGE OverloadedStrings #-}

instance FromJSON Coord where
   parseJSON (Object ob) = LogIn            <$>
                           ob .: "username" <*>
                           ob .: "password"

   parseJSON _          = mzero