使用Aeson

时间:2019-03-16 15:30:48

标签: haskell aeson

我正在尝试编写一个Haskell程序,该程序期望提供Json字符串作为输入。预期的Json是Person对象的列表。我想处理默认情况下用户为空列表的Json不提供输入的情况。 好像我遇到了ByteString和String之间的类型转换问题。我确实打开了OverloadedStrings,但似乎无济于事。这是简化的代码。

{-# LANGUAGE OverloadedStrings #-}
import GHC.Generics
import System.Environment
import Data.Aeson
import Data.Maybe (fromMaybe, listToMaybe)
import Data.Text (Text)

data Person = Person { pName :: Text, pAge :: Int } deriving (Show, 
Generic)
instance ToJSON Person
instance FromJSON Person

main :: IO (Maybe [Person])
main = do
  args <- getArgs
  arg1 <- pure $ (fromMaybe "[]" (listToMaybe args))
  -- let arg1 = "[{\"pName\": \"James\", \"pAge\": 30}]"
  return $ decode arg1 :: IO (Maybe [Person])

我遇到的错误是:

• Couldn't match type ‘[Char]’
                 with ‘Data.ByteString.Lazy.Internal.ByteString’
  Expected type: Data.ByteString.Lazy.Internal.ByteString
    Actual type: String
• In the first argument of ‘decode’, namely ‘arg1’
  In the second argument of ‘($)’, namely ‘decode arg1’
  In a stmt of a 'do' block:
      return $ decode arg1 :: IO (Maybe [Person])

如果我取消注释let arg1以模拟arg1应该是什么,则代码将编译。

1 个答案:

答案 0 :(得分:2)

问题是getArgs返回[String],而不是[ByteString]decode确实希望输入ByteString

OverloadedStrings对此没有帮助;它只会影响代码中的字符串文字,而不会影响外部输入。这就是使用带有硬编码参数(let arg1 = "[{\"pName\": \"James\", \"pAge\": 30}]")的版本起作用的原因:arg1自动成为ByteString以使decode arg1起作用,但是getArgs具有不兼容的类型。

一种可能的解决方法是以某种方式将命令行字符串编码为字节,但是似乎有an easier alternative

import System.Posix.Env.ByteString (getArgs)

给你一个

getArgs :: IO [ByteString]

(我尚未实际测试此代码;您可能还必须使用decodeStrict而不是decode。)