簡體   English   中英

使用Pipes.Aeson在Haskell中流式解析JSON

[英]Streaming parsing of JSON in Haskell with Pipes.Aeson

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 Parser,以及解碼Parser中的Producer。

這可能完全是錯誤的方法。

我的問題,簡而言之:
使用Pipes.Aeson解析文件時,折疊文件中所有對象的最佳方法是什么?

您可以使用Pipes.Aeson.Uncheckeddecoded 解析鏡頭 ,而不是使用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完成解析錯誤和錯誤后的未解析字節,或者原始生成器的返回值()在我們的例子中是() )。

我們可以忽略返回值:

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

和插件生產者成Pipes.Prelude ,像sum

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

在ghci:

λ :main
10

另請注意,這些函數純粹不可避免地允許您應用於foldl包中定義的生成器折疊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM