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

问题描述 投票:0回答:1

我正在尝试编写一个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应该是什么,那么代码编译。

haskell aeson
1个回答
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。)

© www.soinside.com 2019 - 2024. All rights reserved.