httpSink 和解析 json
httpSink and parsing json
我认为这对我来说有点高级,但我的目标是从 http API 获取原始 json,从中解析第一个列表,做任何我需要的这样做然后转到下一个列表,依此类推。我希望这应该允许一次只将一个列表加载到内存中(每个列表都非常小,但是 json 中有很多列表)。
我用 Aeson 试过,它吃光了所有的 ram 并无休止地处理了几个小时,我最终不得不杀死它。
如果我理解正确,httpSink 应该是可行的方法,也许 json-stream 可以进行实际的解析。我阅读了有关管道的教程,但我显然没有正确理解它,因为我无法做到这一点。
我知道如何使用 parseByteString 以我需要的方式解码 ByteString(至少我的测试似乎有效),但我想不出将 parseByteString 用作 httpSink 第二个参数的 Sink 的方法。
我是否遗漏了一些明显的东西,或者我是否误解了管道的工作方式?
谢谢
您写道:
I read the tutorial about conduits, but I'm clearly not understanding it properly since I can't make that work.
I can't figure out a way to use parseByteString as a Sink for httpSink's second parameter.
这里的问题是 Sink
只是管道的简称:
type Sink i m r = ConduitM i Void m r
Sink
是一种没有下游组件的管道。
管道是您需要的解决方案,我假设 this 是您阅读的教程。如果您对其中的某些概念不满意,请尝试提出一个具体问题。
我还没有测试过这个,因为老实说我对这个库不太熟悉,但我认为这个适配器函数可以让它与管道一起工作:
module Data.JsonStream.Parser.Conduit
( jsonConduit
, JsonStreamException (..)
) where
import Data.Conduit
import Data.JsonStream.Parser
import Data.ByteString (ByteString)
import Control.Monad.Catch
import Data.Typeable
jsonConduit
:: MonadThrow m
=> Parser a
-> ConduitM ByteString a m ()
jsonConduit =
go . runParser
where
go (ParseYield x p) = yield x >> go p
go (ParseNeedData f) = await >>= maybe
(throwM JsonStreamNotEnoughData)
(go . f)
go (ParseFailed str) = throwM $ JsonStreamException str
go (ParseDone bs) = leftover bs
data JsonStreamException
= JsonStreamException !String
| JsonStreamNotEnoughData
deriving (Show, Typeable)
instance Exception JsonStreamException
我认为这对我来说有点高级,但我的目标是从 http API 获取原始 json,从中解析第一个列表,做任何我需要的这样做然后转到下一个列表,依此类推。我希望这应该允许一次只将一个列表加载到内存中(每个列表都非常小,但是 json 中有很多列表)。 我用 Aeson 试过,它吃光了所有的 ram 并无休止地处理了几个小时,我最终不得不杀死它。
如果我理解正确,httpSink 应该是可行的方法,也许 json-stream 可以进行实际的解析。我阅读了有关管道的教程,但我显然没有正确理解它,因为我无法做到这一点。
我知道如何使用 parseByteString 以我需要的方式解码 ByteString(至少我的测试似乎有效),但我想不出将 parseByteString 用作 httpSink 第二个参数的 Sink 的方法。 我是否遗漏了一些明显的东西,或者我是否误解了管道的工作方式?
谢谢
您写道:
I read the tutorial about conduits, but I'm clearly not understanding it properly since I can't make that work.
I can't figure out a way to use parseByteString as a Sink for httpSink's second parameter.
这里的问题是 Sink
只是管道的简称:
type Sink i m r = ConduitM i Void m r
Sink
是一种没有下游组件的管道。
管道是您需要的解决方案,我假设 this 是您阅读的教程。如果您对其中的某些概念不满意,请尝试提出一个具体问题。
我还没有测试过这个,因为老实说我对这个库不太熟悉,但我认为这个适配器函数可以让它与管道一起工作:
module Data.JsonStream.Parser.Conduit
( jsonConduit
, JsonStreamException (..)
) where
import Data.Conduit
import Data.JsonStream.Parser
import Data.ByteString (ByteString)
import Control.Monad.Catch
import Data.Typeable
jsonConduit
:: MonadThrow m
=> Parser a
-> ConduitM ByteString a m ()
jsonConduit =
go . runParser
where
go (ParseYield x p) = yield x >> go p
go (ParseNeedData f) = await >>= maybe
(throwM JsonStreamNotEnoughData)
(go . f)
go (ParseFailed str) = throwM $ JsonStreamException str
go (ParseDone bs) = leftover bs
data JsonStreamException
= JsonStreamException !String
| JsonStreamNotEnoughData
deriving (Show, Typeable)
instance Exception JsonStreamException