【问题标题】:Problem decoding json from input args with Aeson使用 Aeson 从输入 args 解码 json 时出现问题
【发布时间】:2019-03-16 15:30:48
【问题描述】:

我正在尝试编写一个期望提供 Json 字符串作为输入的 Haskell 程序。预期的 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 应该是什么,则代码编译。

【问题讨论】:

  • arg1 &lt;- pure $ ... 可以写成let arg1 = ...

标签: haskell aeson


【解决方案1】:

问题在于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。)

【讨论】:

  • 感谢您的帮助。为什么在 Haskell 中进行此类转换如此具有挑战性?...我尝试了您的建议,现在我收到此错误 Couldn't match expected type ‘Data.ByteString.Lazy.Internal.ByteString’ with actual type ‘Data.ByteString.Internal.ByteString’
  • “为什么这么难”部分是因为你不知道如何转换,部分是因为转换是由库提供的,而不是内置在语言中的。如果你知道怎么做,那么它就变得容易了。您可以将 8 位字符的 pack 字符串转换为字节串。您可以使用 UTF8(或其他编码)对它们进行编码。或许多其他解决方案之一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 2019-07-19
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多