haskell - 如何在不声明单个类型的情况下使用 Aeson 解析 JSON

标签 haskell aeson

(Haskell 新手警报)

这是我正在努力解决的代码片段。基本上,我从 websocket 获取 JSON,我想使用 Aeson 解析它,而不为每个响应定义单独的数据类型。

import Data.Aeson
import qualified Network.WebSockets  as WS

aria2WebsocketReceiver :: WS.Connection -> IO ()
aria2WebsocketReceiver conn = do
  msg <- WS.receiveData conn
  let res = decode msg
  let v = flip parseMaybe res $ \o -> do
                                      r <- o .: "result"
                                      version <- r .: "version"
                                      enabledFeatures <- r .: "enabledFeatures"
                                      id_ <- r .: "id"
                                      return $ "version=" ++ version
  putStrLn (show v)
  aria2WebsocketReceiver conn

以下是我遇到的编译错误:

Nightwatch/Telegram.hs:244:13:
    No instance for (FromJSON a0) arising from a use of ‘decode’
    The type variable ‘a0’ is ambiguous
    Relevant bindings include
      res :: Maybe a0 (bound at Nightwatch/Telegram.hs:244:7)
    Note: there are several potential instances:
      instance FromJSON Chat -- Defined at Nightwatch/Telegram.hs:90:10
      instance FromJSON Message
        -- Defined at Nightwatch/Telegram.hs:106:10
      instance FromJSON TelegramResponse
        -- Defined at Nightwatch/Telegram.hs:122:10
      ...plus two others
    In the expression: decode msg
    In an equation for ‘res’: res = decode msg
    In the expression:
      do { msg <- WS.receiveData conn;
           let res = decode msg;
           let v = flip parseMaybe res $ ...;
           putStrLn (show v);
           .... }

Nightwatch/Telegram.hs:246:44:
    Couldn't match type ‘Maybe a0’
                   with ‘unordered-containers-0.2.5.1:Data.HashMap.Base.HashMap
                           Text Value’
    Expected type: Object
      Actual type: Maybe a0
    Relevant bindings include
      o :: Maybe a0 (bound at Nightwatch/Telegram.hs:245:34)
      res :: Maybe a0 (bound at Nightwatch/Telegram.hs:244:7)
    In the first argument of ‘(.:)’, namely ‘o’
    In a stmt of a 'do' block: r <- o .: "result"

我基本上是在尝试复制 https://hackage.haskell.org/package/aeson-0.10.0.0/docs/Data-Aeson.html 中给出的“使用 AST”示例

最佳答案

感谢 #haskell 的 Cale,这是工作代码:

aria2WebsocketReceiver :: WS.Connection -> IO ()
aria2WebsocketReceiver conn = do
  msg <- WS.receiveData conn
  let v = do res <- decode msg
             flip parseMaybe res $ \o -> do
                                         r <- o .: "result"
                                         version <- r .: "version"
                                         return $ "version=" ++ (version :: String)
  putStrLn (show v)
  aria2WebsocketReceiver conn

早期代码存在三个问题:

  1. decode msg 的类型是 Maybe,需要位于单独的 do block 内。
  2. 由于 {-# LANGUAGE OverloadedStrings #-},编译器无法推断 version 的类型,因此 (version::字符串)提示。
  3. 同样,enabledFeaturesid_ 已被分配但未在任何地方使用,这导致了类型推断中的更多问题。

关于haskell - 如何在不声明单个类型的情况下使用 Aeson 解析 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35077554/

相关文章:

json - 使用 Aeson 解析有问题的 JSON

haskell - 为什么图书馆设计者在 Text 似乎合适的地方使用 ByteString?

haskell - 对多个 'Main' 进行类型检查

list - 在 Haskell 中将任何类型的列表作为函数参数(使用 Replit)

haskell - 如何将类型构造函数限制为返回 Ord 类型?

json - 将 Haskell JSON Lens 表达式转换回 JSON

json - 将选项对象解析为选项列表

haskell中构造函数的内存使用情况

haskell - 不使用 monad 进行表示法 : possible?

json - 在 Haskell 中解析/导出任意嵌套的 JSON 对象到映射