@@ -10,9 +10,9 @@ import qualified Data.ByteString.Lazy as LBS
1010import Data.Either
1111import Data.Foldable (toList )
1212import qualified Data.HashMap.Strict as HM
13- import Data.IORef
1413import Data.HashSet (HashSet , empty , intersection , null , union )
1514import qualified Data.HashSet as HS (toList )
15+ import Data.IORef
1616import Data.Text (Text , intercalate )
1717import qualified Data.Text.IO as TIO
1818import Deque.Strict (Deque )
@@ -21,28 +21,31 @@ import GHC.Exts (fromList)
2121import Json2Csv
2222import Options.Applicative hiding (empty )
2323import Options.Applicative.Text
24- import Prelude hiding (foldl , foldl' , map , null , sequence )
2524import Schema
2625import System.IO
26+ import System.ProgressBar
27+ import Prelude hiding (foldl , foldl' , map , null , sequence )
2728
28- data Args = Args {
29- jsonFile :: String ,
30- csvFile :: String ,
31- separator :: Text ,
32- isect :: Bool ,
33- flatArr :: Bool
34- }
29+ data Args = Args
30+ { jsonFile :: String ,
31+ csvFile :: String ,
32+ separator :: Text ,
33+ isect :: Bool ,
34+ flatArr :: Bool
35+ }
3536
3637type PathSet = HashSet JsonPath
38+
3739type PathSetCombine = PathSet -> PathSet -> PathSet
3840
3941args :: Parser Args
40- args = Args
41- <$> strArgument (metavar " jsonFile" <> help " Newline-delimited JSON input file name" )
42- <*> strArgument (metavar " csvFile" <> help " CSV output file name" )
43- <*> textOption (long " separator" <> help " CSV separator" <> showDefault <> value " ;" )
44- <*> switch (long " intersect" <> short ' i' <> help " \" Inner join\" fields while constructing schema" )
45- <*> switch (long " flatten" <> short ' f' <> help " Flatten array iterators" )
42+ args =
43+ Args
44+ <$> strArgument (metavar " jsonFile" <> help " Newline-delimited JSON input file name" )
45+ <*> strArgument (metavar " csvFile" <> help " CSV output file name" )
46+ <*> textOption (long " separator" <> help " CSV separator" <> showDefault <> value " ;" )
47+ <*> switch (long " intersect" <> short ' i' <> help " \" Inner join\" fields while constructing schema" )
48+ <*> switch (long " flatten" <> short ' f' <> help " Flatten array iterators" )
4649
4750argsInfo :: ParserInfo Args
4851argsInfo = info args fullDesc
@@ -59,31 +62,35 @@ main = do
5962 let combine = if (isect arguments) then isectOrNonEmpty else flip union
6063 let flat = flatArr arguments
6164 let procCols = if (flat) then dropIterators else id
62- header <- withFile (jsonFile arguments) ReadMode $ computeHeaderMultiline combine
65+ ( header, numberOfLines) <- withFile (jsonFile arguments) ReadMode $ computeHeaderMultiline combine
6366 let schema = toSchema header
6467 let columns = jsonPathText <$> (uniq $ procCols <$> header)
68+ pb <- newProgressBar defStyle 10 (Progress 0 numberOfLines () )
6569 withFile (jsonFile arguments) ReadMode $ \ hIn ->
6670 withFile (csvFile arguments) WriteMode $ \ hOut -> do
6771 hSetEncoding hIn utf8
6872 hSetEncoding hOut utf8
6973 TIO. hPutStrLn hOut $ mkSepString $ columns
70- whileM_ (not <$> hIsEOF hIn) (parseAndWriteEntry mkSepString flat schema columns hIn hOut)
74+ whileM_ (not <$> hIsEOF hIn) $ do
75+ (parseAndWriteEntry mkSepString flat schema columns hIn hOut)
76+ incProgress pb 1
7177
72- computeHeaderMultiline :: PathSetCombine -> Handle -> IO (Deque JsonPath )
78+ computeHeaderMultiline :: PathSetCombine -> Handle -> IO (Deque JsonPath , Int )
7379computeHeaderMultiline combine handle = do
7480 currentLineNumber <- newIORef (0 :: Int )
7581 pathSet <- newIORef (empty :: HashSet JsonPath )
7682 whileM_ (not <$> hIsEOF handle) $ do
77- modifyIORef' currentLineNumber (1 + )
78- line <- LBS. fromStrict <$> BS. hGetLine handle
79- ln <- readIORef currentLineNumber
80- parsed <- case eitherDecode' line of
81- Right value -> pure value
82- Left err -> fail $ " Can't parse JSON at line " ++ (show ln) ++ " : " ++ err
83- let (Just header) = computePaths True parsed
84- modifyIORef' pathSet (combine header)
83+ modifyIORef' currentLineNumber (1 + )
84+ line <- LBS. fromStrict <$> BS. hGetLine handle
85+ ln <- readIORef currentLineNumber
86+ parsed <- case eitherDecode' line of
87+ Right value -> pure value
88+ Left err -> fail $ " Can't parse JSON at line " ++ (show ln) ++ " : " ++ err
89+ let (Just header) = computePaths True parsed
90+ modifyIORef' pathSet (combine header)
8591 pathes <- readIORef pathSet
86- return $ fromList . HS. toList $ pathes
92+ numberOfLines <- readIORef currentLineNumber
93+ return (fromList . HS. toList $ pathes, numberOfLines)
8794
8895parseAndWriteEntry :: (Deque Text -> Text ) -> Bool -> JsonSchema -> Deque Text -> Handle -> Handle -> IO ()
8996parseAndWriteEntry mkSepString flat schema columns hIn hOut = do
0 commit comments