【问题标题】:Streaming parsing of JSON in Haskell with Pipes.Aeson使用 Pipes.Aeson 在 Haskell 中对 JSON 进行流式解析
【发布时间】:2014-05-17 18:28:37
【问题描述】:

Pipes.Aeson 库公开了以下函数:

decode :: (Monad m, ToJSON a) => Parser ByteString m (Either DecodingError a)

如果我将此解析器与文件句柄一起使用 evalStateT 作为参数,则会从文件中读取单个 JSON 对象并进行解析。

问题是该文件包含多个对象(所有类型都相同),我想在读取它们时折叠或缩小它们。

Pipes.Parse 提供:

foldAll :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Parser a m b

但是正如你所看到的,这会返回一个新的解析器——我想不出一种将第一个解析器作为参数提供的方法。

看起来 Parser 实际上是 StateT monad 转换器中的 Producer。我想知道是否有一种方法可以从 StateT 中提取 Producer,以便 evalStateT 可以应用于 foldAll 解析器,以及来自 decode Parser 的 Producer。

这可能是完全错误的方法。

我的问题,简而言之:
使用 Pipes.Aeson 解析文件时,折叠文件中所有对象的最佳方法是什么?

【问题讨论】:

    标签: json parsing haskell aeson haskell-pipes


    【解决方案1】:

    您可以使用来自Pipes.Aeson.Uncheckeddecoded parsing lens,而不是使用decode。它将ByteString 的生产者转变为解析后的 JSON 值的生产者。

    {-# LANGUAGE OverloadedStrings #-}
    
    module Main where
    
    import Pipes
    import qualified Pipes.Prelude as P
    import qualified Pipes.Aeson as A
    import qualified Pipes.Aeson.Unchecked as AU
    import qualified Data.ByteString as B
    
    import Control.Lens (view)
    
    byteProducer :: Monad m => Producer B.ByteString m ()
    byteProducer = yield "1 2 3 4"
    
    intProducer :: Monad m => Producer Int m (Either (A.DecodingError, Producer B.ByteString m ()) ())
    intProducer = view AU.decoded byteProducer
    

    intProducer 的返回值有点吓人,但这仅意味着intProducer 要么以解析错误和错误后未解析的字节结束,要么以原始生产者的返回值(即@ 987654335@ 在我们的例子中)。

    我们可以忽略返回值:

    intProducer' :: Monad m => Producer Int m ()
    intProducer' = intProducer >> return ()
    

    并将生产者插入Pipes.Prelude 中的fold,例如sum

    main :: IO ()
    main = do
        total <- P.sum intProducer'
        putStrLn $ show total
    

    在 ghci 中:

    λ :main
    10
    

    另请注意,purelyimpurely 函数可让您应用于 foldl 包中定义的生产者折叠。

    【讨论】:

    • 你也可以zoom decoded (foldAll step begin done)
    • @GabrielGonzalez 啊是的,我忘记了也可以使用zoom将镜头应用于Parsers。
    • @GabrielGonzalez 另外,使用zoom decoded ... 似乎更容易处理解析错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多