使用 Aeson 从输入参数解码 json 时出现问题

Problem decoding json from input args with 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 应该是什么,然后代码编译。

问题是 getArgs returns 一个 [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。)