使用Pipes.Aeson在Haskell中对JSON进行流式解析
Pipes.Aeson库公开了以下功能:使用Pipes.Aeson在Haskell中对JSON进行流式解析,json,parsing,haskell,aeson,haskell-pipes,Json,Parsing,Haskell,Aeson,Haskell Pipes,Pipes.Aeson库公开了以下功能: decode :: (Monad m, ToJSON a) => Parser ByteString m (Either DecodingError a) 如果将evalStateT与此解析器和文件句柄一起用作参数,则会从文件中读取一个JSON对象并进行解析 问题是文件包含多个对象(所有对象都是同一类型的),我希望在读取时折叠或缩小它们 Parse提供: foldAll :: Monad m => (x -> a -> x) -
decode :: (Monad m, ToJSON a) => Parser ByteString m (Either DecodingError a)
如果将evalStateT与此解析器和文件句柄一起用作参数,则会从文件中读取一个JSON对象并进行解析
问题是文件包含多个对象(所有对象都是同一类型的),我希望在读取时折叠或缩小它们
Parse提供:
foldAll :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Parser a m b
但正如您所看到的,这将返回一个新的解析器——我想不出一种方法来提供第一个解析器作为参数
看起来解析器实际上是StateT monad转换器中的生产者。我想知道是否有一种方法可以从StateT中提取生产者,以便evalStateT可以应用于foldAll解析器,而生产者可以应用于decode解析器
但这可能是完全错误的方法
简而言之,我的问题是:使用Pipes.Aeson解析文件时,折叠文件中所有对象的最佳方法是什么?您可以使用from
Pipes.Aeson.Unchecked
而不是使用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 ()
并将制作人插入一个from管道。前奏曲,如:
还请注意,函数和允许您应用于包中定义的折叠。您还可以执行缩放解码(foldAll step begin done)
@GabrielGonzalez啊,是的,我忘了还可以使用缩放
将镜头应用于解析器
s.@GabrielGonzalez,似乎使用zoom decoded…
可以更容易地处理解析错误。
main :: IO ()
main = do
total <- P.sum intProducer'
putStrLn $ show total
λ :main
10