在ByteString中找到一个值(实际上是JSON)

时间:2014-06-27 14:56:02

标签: json haskell

网络服务返回ByteString

的回复
  req <- parseUrl "https://api.example.com"
  res <- withManager $ httpLbs $ configReq req
  case (HashMap.lookup "result" $ responseBody res) of .... -- error - responseBody returns ByteString


  where 
    configReq r = --......

更具体地说,responseBody会返回ByteString中的数据,尽管它实际上是有效的JSON。我需要在其中找到一个值。显然,如果它是JSON而不是ByteString,那么找到它会更容易。

如果是这种情况,我该如何将其转换为JSON?

更新:

decode $ responseBody resp :: IO (Either String Aeson.Value)

错误:

Couldn't match expected type `IO (Either String Value)'
                with actual type `Maybe a0'

1 个答案:

答案 0 :(得分:2)

您将找到几个用于将bytestring转换为JSON的资源。最简单的用例是在hackage页面本身,其余的你可以推断使用所涉及实体的类型签名。

https://hackage.haskell.org/package/aeson-0.7.0.6/docs/Data-Aeson.html

但是这是Aeson与JSON的超级快速介绍: 在大多数语言中,你有这样的东西:

someString = '{ "name" : ["value1", 2] }'
aDict = json.loads(someString)

这显然很棒,因为JSON具有与该语言的基本数据结构几乎一对一的映射。大多数动态语言中的容器可以包含任何类型的值,因此从JSON迁移到数据结构只需一步。

然而,Haskell并非如此。您不能将任意类型的东西放入类型(列表或字典)之类的容器中。

所以Aeson做了一件好事。它为您定义了一个中间Haskell类型,它直接映射到JSON。

Aeson中的基本单位是Value。价值可以包含很多东西。像整数,字符串,数组或对象一样。

https://hackage.haskell.org/package/aeson-0.7.0.6/docs/Data-Aeson.html#t:Value

aeson数组是Vector的{​​{1}}(如同列表但更好),Value和aeson对象是HashMap TextValue的{​​{1}}小号

下一个有趣的步骤是您可以定义将Aeson值转换为Haskell类型的函数。这样就完成了循环。自定义类型的ByteStringValue

所以你要做的就是实现{a {1}}和parseJSON函数,将aeson值转换为你的类型,反之亦然。将字节串转换为有效的aeson值的位由aeson实现。因此,繁重的工作都已完成。

重要的是要注意,Aeson bytestring是一个懒惰的字节串,所以你可能需要一些严格的懒惰助手。

toJSON

这应该足以开始使用Aeson。

-

Aeson的常见解码功能:

stringToLazy :: String -> ByteString
stringToLazy x = Data.Bytestring.Lazy.fromChunks [(Data.ByteString.Char8.pack x)]

lazyToString :: ByteString -> String
lazyToString x = Data.ByteString.Char8.unpack $ Data.ByteString.Char8.concat $ Data.ByteString.Lazy.toChunks

在你的情况下,你正在寻找代码。