如何使用Data.Text.Lazy.IO用Aeson解析JSON文件

如何使用Data.Text.Lazy.IO用Aeson解析JSON文件,第1张

概述我想将给定目录中的所有json文件解析为数据类型Result. 所以我有一个解码功能 decodeResult :: Data.ByteString.Lazy.ByteString -> Maybe Result 我从Data.Text.Lazy.IO开始将文件加载到Lazy ByteString中, import qualified Data.Text.Lazy.IO as Timport q 我想将给定目录中的所有Json文件解析为数据类型Result.

所以我有一个解码功能

decodeResult :: Data.ByteString.Lazy.ByteString -> Maybe Result

我从Data.Text.Lazy.IO开始将文件加载到Lazy ByteString中,

import qualifIEd Data.Text.Lazy.IO as Timport qualifIEd Data.Text.Lazy.EnCoding as TgetfileContent :: filePath -> IO B.ByteStringgetfileContent path = T.encodeUtf8 `fmap` T.readfile path

它编译了,但我遇到了太多文件打开的问题,所以我想也许我应该使用withFile.

import System.IOimport qualifIEd Data.ByteString.Lazy as Bimport qualifIEd Data.Text.Lazy.IO as Timport qualifIEd Data.Text.Lazy.EnCoding as TgetfileContent :: filePath -> IO (Maybe Result)getfileContent path = withfile path ReadMode $\hnd -> do   content <- T.hGetContents hnd   return $(decodeAnalytic . T.encodeUtf8) contentloadAllResults :: filePath -> IO [Result]loadAllResults path = do   paths <- ListDirectory path   results <- sequence $fmap getfileContent (fmap (path ++ ) $filter (endswith ".Json") paths)   return $catMaybes results

在这个版本中,懒惰的io似乎永远不会被评估,它总是返回空列表.但是如果我在getfileContent函数中打印内容,那么一切似乎都能正常工作.

getfileContent :: filePath -> IO (Maybe Result)getfileContent path = withfile path ReadMode $\hnd -> do   content <- T.hGetContents hnd   print content   return $(decodeAnalytic . T.encodeUtf8) content

所以我不确定我错过了什么,我应该使用导管来做这类事吗?

解决方法 一般来说,我建议使用流式库来解析像JsON文件这样的任意大小的数据.但是,在使用aeson解析JsON的特定情况下,超出内存的问题并不像IMO那么重要,因为aeson库本身最终将内存中的整个文件表示为Value类型.因此,您可以选择简单地使用严格的字节串I / O.我给出了一个使用管道和严格I / O来解析JsON值的示例. (我认为导管版本已存在于某些库中,我不确定.)

#!/usr/bin/env stack{- stack --resolver lts-7.14 --install-ghc runghc   --package aeson --package conduit-extra-}import           Control.Monad.Catch     (MonadThrow,throwM)import           Control.Monad.IO.Class  (Monadio,liftIO)import           Data.Aeson              (FromJsON,Result (..),eitherDecodeStrict',fromJsON,Json,Value)import           Data.ByteString         (ByteString)import qualifIEd Data.ByteString         as Bimport           Data.Conduit            (ConduitM,runconduitRes,(.|))import           Data.Conduit.Attoparsec (sinkParser)import           Data.Conduit.Binary     (sourcefile)sinkFromJsON :: (MonadThrow m,FromJsON a) => ConduitM ByteString o m asinkFromJsON = do    value <- sinkParser Json    case fromJsON value of        Error e -> throwM $userError e        Success x -> return xreadJsONfile :: (Monadio m,FromJsON a) => filePath -> m areadJsONfile fp = liftIO $runconduitRes $sourcefile fp .| sinkFromJsON-- Or using strict I/OreadJsONfileStrict :: (Monadio m,FromJsON a) => filePath -> m areadJsONfileStrict fp = liftIO $do    bs <- B.readfile fp    case eitherDecodeStrict' bs of        left e -> throwM $userError e        Right x -> return xmain :: IO ()main = do    x <- readJsONfile "test.Json"    y <- readJsONfileStrict "test.Json"    print (x :: Value)    print (y :: Value)

编辑忘记提及:我强烈建议不要使用文本I / O来读取您的JsON文件. JsON文件应使用UTF-8编码,而文本I / O函数将使用系统设置指定的任何字符编码.依靠Data.ByteString.readfile和类似的更可靠.我详细介绍了in a recent blog post.

总结

以上是内存溢出为你收集整理的如何使用Data.Text.Lazy.IO用Aeson解析JSON文件全部内容,希望文章能够帮你解决如何使用Data.Text.Lazy.IO用Aeson解析JSON文件所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1070876.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存