json-tools 0.3.1 → 0.4.0
raw patch · 13 files changed
+203/−176 lines, 13 filesdep +aesondep +textdep +unordered-containersdep −AttoJsondep −convertible-textdep −data-objectdep ~tarnew-component:exe:json-quote
Dependencies added: aeson, text, unordered-containers, vector
Dependencies removed: AttoJson, convertible-text, data-object, data-object-json
Dependency ranges changed: tar
Files
- Utils.hs +14/−21
- json-concat.hs +12/−10
- json-deep-select-key.hs +15/−12
- json-iter.hs +6/−5
- json-lines.hs +15/−13
- json-quote.hs +6/−0
- json-select.hs +52/−49
- json-strings.hs +19/−14
- json-tools.cabal +16/−10
- json-unlines.hs +2/−2
- json-wrap.hs +15/−11
- json-xargs.hs +15/−13
- tar2json.hs +16/−16
Utils.hs view
@@ -1,48 +1,41 @@ {-# LANGUAGE ScopedTypeVariables #-} module Utils- ( readFilesL, readFilesS, decodeFile, parseJSONFiles+ ( readFiles, decodeFile, parseJSONFiles , systemWithStdin) where -import Text.JSON.AttoJSON+import Data.Aeson+import Data.Maybe import Data.Functor import Control.Exception-import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L import System.IO (hClose) import System.Exit (ExitCode) import System.IO.Unsafe (unsafeInterleaveIO) import qualified System.Process as P -readFilesL :: [String] -> IO [L.ByteString]-readFilesL args+readFiles :: [String] -> IO [L.ByteString]+readFiles args | null args = fmap (:[]) L.getContents | otherwise = mapM file args where file "-" = L.getContents file xs = L.readFile xs -readFilesS :: [String] -> IO [S.ByteString]-readFilesS args- | null args = fmap (:[]) S.getContents- | otherwise = mapM file args- where file "-" = S.getContents- file xs = S.readFile xs--decodeFile :: FilePath -> IO (Either String JSValue)-decodeFile fp = parseJSON <$> S.readFile fp+decodeFile :: FilePath -> IO (Maybe Value)+decodeFile fp = decode' <$> L.readFile fp -decErr :: String -> a-decErr s = error $ "JSON decoding: " ++ s+decErr :: a+decErr = error "JSON decoding" -parseJSONFiles :: [FilePath] -> IO [JSValue]-parseJSONFiles [] = (:[]) . either decErr id . parseJSON <$> S.getContents-parseJSONFiles xs = mapM (unsafeInterleaveIO . fmap (either decErr id) . decodeFile) xs+parseJSONFiles :: [FilePath] -> IO [Value]+parseJSONFiles [] = (:[]) . fromMaybe decErr . decode' <$> L.getContents+parseJSONFiles xs = mapM (unsafeInterleaveIO . fmap (fromMaybe decErr) . decodeFile) xs -systemWithStdin :: String -> S.ByteString -> IO ExitCode+systemWithStdin :: String -> L.ByteString -> IO ExitCode systemWithStdin shellCmd input = do (Just stdinHdl, _, _, pHdl) <- P.createProcess (P.shell shellCmd){ P.std_in = P.CreatePipe } handle (\(_ :: IOException) -> return ()) $ do- S.hPutStr stdinHdl input+ L.hPutStr stdinHdl input hClose stdinHdl P.waitForProcess pHdl
json-concat.hs view
@@ -1,5 +1,7 @@-import Text.JSON.AttoJSON-import qualified Data.ByteString as S+import Data.Aeson+import qualified Data.Vector as V+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8 import Control.Monad (when) import System.IO (hPutStrLn, stderr) import System.Exit (exitFailure)@@ -16,11 +18,11 @@ main :: IO () main = do args <- getArgs when (not . null $ args) usage- S.putStrLn . showJSON . jsonConcat . either err id . parseJSON- =<< S.getContents- where jsonConcat (JSArray a) = JSArray (concatMap unJSArray a)- jsonConcat (JSObject _) = error "unexpected non-JSON array"- jsonConcat _ = error "not a JSON document (neither array, nor object)"- unJSArray (JSArray a) = a- unJSArray _ = error "unexpected non-JSON array"- err s = error $ "JSON decoding: " ++ s+ L8.putStrLn . encode . jsonConcat . maybe err id . decode'+ =<< L.getContents+ where jsonConcat (Array a) = Array (V.concatMap unArray a)+ jsonConcat (Object _) = error "unexpected non-JSON array"+ jsonConcat _ = error "not a JSON document (neither array, nor object)"+ unArray (Array a) = a+ unArray _ = error "unexpected non-JSON array"+ err = error "JSON decoding error"
json-deep-select-key.hs view
@@ -1,22 +1,25 @@-import qualified Data.Map as M-import Text.JSON.AttoJSON+import qualified Data.HashMap.Strict as HM+import Data.Aeson+import qualified Data.Text as T import System.Environment (getArgs)-import qualified Data.ByteString as S-import qualified Data.ByteString.Char8 as S8+import qualified Data.Vector as V+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8 -deepSelectKey :: S.ByteString -> JSValue -> [JSValue]-deepSelectKey key (JSArray vs)- = concatMap (deepSelectKey key) vs-deepSelectKey key (JSObject o)- = maybe (concatMap (deepSelectKey key) (map snd (M.toList o))) return . M.lookup key $ o-deepSelectKey _ _ = []+deepSelectKey :: T.Text -> Value -> V.Vector Value+deepSelectKey key (Array vs)+ = V.concatMap (deepSelectKey key) vs+deepSelectKey key (Object o)+ = maybe (V.concatMap (deepSelectKey key) (V.fromList $ HM.elems o)) return+ . HM.lookup key $ o+deepSelectKey _ _ = V.empty main :: IO () main = do args <- getArgs- obj <- either fail return . parseJSON =<< S.getContents+ obj <- maybe (fail "JSON decoding") return . decode' =<< L.getContents case args of [key] ->- S.putStrLn . showJSON . JSArray $ deepSelectKey (S8.pack key) obj+ L8.putStrLn . encode . Array $ deepSelectKey (T.pack key) obj _ -> error "Usage: json-deep-select-key <key>"
json-iter.hs view
@@ -2,16 +2,17 @@ import System.IO (hPutStrLn, stderr) import System.Exit (exitFailure) import Control.Monad (when)-import Text.JSON.AttoJSON+import Data.Aeson import Utils (parseJSONFiles, systemWithStdin)+import qualified Data.Vector as V -unSequence :: JSValue -> [JSValue]-unSequence (JSArray a) = a-unSequence _ = error "unSequence: a JSON sequence was expected"+unSequence :: Value -> [Value]+unSequence (Array a) = V.toList a+unSequence _ = error "unSequence: a JSON sequence was expected" iterJSON :: String -> [String] -> IO () iterJSON cmd jsonfiles =- mapM_ (mapM_ (systemWithStdin cmd . showJSON) . unSequence)+ mapM_ (mapM_ (systemWithStdin cmd . encode) . unSequence) =<< parseJSONFiles jsonfiles usage :: IO a
json-lines.hs view
@@ -1,14 +1,16 @@-import Text.JSON.AttoJSON-import qualified Data.ByteString.Char8 as S+import Data.Aeson+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8 import Control.Monad (when) import System.Environment (getArgs) import System.Exit (exitFailure) import System.IO (hPutStrLn,stderr)-import Utils (readFilesS)+import Utils (readFiles)+import qualified Data.Vector as V -jsonUnlines :: JSValue -> [JSValue]-jsonUnlines (JSArray xs) = xs-jsonUnlines _ = error "Unexpected JSON value, only an array was expected"+jsonUnlines :: Value -> [Value]+jsonUnlines (Array xs) = V.toList xs+jsonUnlines _ = error "Unexpected JSON value, only an array was expected" usage :: IO a usage = mapM_ (hPutStrLn stderr)@@ -23,13 +25,13 @@ main = do args <- getArgs when ("--help"`elem`args) usage- S.putStr -- printing the output- . S.unlines -- joining lines- . map showJSON -- showing each item+ L.putStr -- printing the output+ . L8.unlines -- joining lines+ . map encode -- showing each item . concat -- merge lines from all files . map ( -- for each file jsonUnlines -- main processing- . either err id -- error handling- . parseJSON -- parsing each file as JSON- ) =<< readFilesS args -- reading the input- where err msg = error $ "JSON parsing: "++msg+ . maybe err id -- error handling+ . decode' -- parsing each file as JSON+ ) =<< readFiles args -- reading the input+ where err = error "JSON decoding error"
+ json-quote.hs view
@@ -0,0 +1,6 @@+import Data.Aeson+import Data.ByteString.Lazy.Char8 as L8+import System.Environment++main :: IO ()+main = L8.putStrLn . encode =<< getArgs
json-select.hs view
@@ -1,52 +1,54 @@ import Data.List import Data.Monoid-import qualified Data.Map as M+import qualified Data.HashMap.Strict as HM import Control.Arrow-import Text.JSON.AttoJSON+import Data.Aeson import System.Environment (getArgs) import System.IO (stderr, hPutStrLn) import System.Exit-import qualified Data.ByteString as S--type JSObject a = M.Map S.ByteString a+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8+import Data.Text (Text)+import qualified Data.Vector as V -data JSFrame = JSArrayFrm [JSValue] [JSValue]- | JSObjectFrm S.ByteString (JSObject JSValue)+data Frame = ArrayFrm Array Array+ | ObjectFrm Text Object deriving (Show) -type JSContext = [JSFrame]+type Context = [Frame] -data JSSegment = JSArrayIndex Int- | JSObjectKey S.ByteString-type JSPath = [JSSegment]+data Segment = ArrayIndex Int+ | ObjectKey Text+type Path = [Segment] -type JSMultiPath = [Maybe JSSegment] -- Nothing means '*'+type MultiPath = [Maybe Segment] -- Nothing means '*' -type JSCxtValue = (JSContext, JSValue)+type CxtValue = (Context, Value) -segmentFromFrame :: JSFrame -> JSSegment-segmentFromFrame (JSArrayFrm prefix _) = JSArrayIndex (length prefix)-segmentFromFrame (JSObjectFrm f _) = JSObjectKey f+segmentFromFrame :: Frame -> Segment+segmentFromFrame (ArrayFrm prefix _) = ArrayIndex (V.length prefix)+segmentFromFrame (ObjectFrm f _) = ObjectKey f -pathFromContext :: JSContext -> JSPath+pathFromContext :: Context -> Path pathFromContext = map segmentFromFrame -selectJSONSegment :: JSSegment -> JSValue -> Either String (JSFrame, JSValue)-selectJSONSegment (JSArrayIndex ix) (JSArray vs)- = case splitAt ix vs of- (prefix, v : suffix) -> Right (JSArrayFrm prefix suffix, v)- (_, []) -> Left msg+selectJSONSegment :: Segment -> Value -> Either String (Frame, Value)+selectJSONSegment (ArrayIndex ix) (Array vs)+ = case V.splitAt ix vs of+ (prefix, suffix)+ | V.null suffix -> Left msg+ | otherwise -> Right (ArrayFrm prefix (V.tail suffix), V.head suffix) where msg = "An array with an index "++show ix++" was expected"-selectJSONSegment (JSObjectKey f) (JSObject o)- = maybe (Left msg) ok . M.lookup f $ o+selectJSONSegment (ObjectKey f) (Object o)+ = maybe (Left msg) ok . HM.lookup f $ o where msg = "An object with a field "++show f++" was expected"- ok x = Right (JSObjectFrm f (M.delete f o), x)-selectJSONSegment (JSArrayIndex _) _+ ok x = Right (ObjectFrm f (HM.delete f o), x)+selectJSONSegment (ArrayIndex _) _ = Left "An array was expected"-selectJSONSegment (JSObjectKey _) _+selectJSONSegment (ObjectKey _) _ = Left "An object was expected" -selectJSON :: JSCxtValue -> JSPath -> (JSContext, Either String JSValue)+selectJSON :: CxtValue -> Path -> (Context, Either String Value) selectJSON (cxt,val) [] = (cxt, Right val) selectJSON (cxt,val) (seg:path) = either ((,)cxt . Left) (flip selectJSON path . first (:cxt)) (selectJSONSegment seg val)@@ -57,33 +59,34 @@ where go sx x [] = [f (reverse sx) x []] go sx x xs@(xs'x : xs'xs) = f (reverse sx) x xs : go (x : sx) xs'x xs'xs -allSubValues :: JSCxtValue -> [JSCxtValue]-allSubValues (_, JSArray []) = []-allSubValues (cxt, JSArray vs) = zips f vs- where f prefix value suffix = (JSArrayFrm prefix suffix : cxt, value)-allSubValues (cxt, JSObject o) = map (first f) . M.toList $ o- where f key = JSObjectFrm key (M.delete key o) : cxt+allSubValues :: CxtValue -> [CxtValue]+allSubValues (cxt, Array vs)+ | V.null vs = []+ | otherwise = zips f (V.toList vs)+ where f prefix value suffix = (ArrayFrm (V.fromList prefix) (V.fromList suffix) : cxt, value)+allSubValues (cxt, Object o) = map (first f) . HM.toList $ o+ where f key = ObjectFrm key (HM.delete key o) : cxt allSubValues _ = [] -selectJSONMaybeSegment :: Maybe JSSegment -> JSCxtValue -> [JSCxtValue]+selectJSONMaybeSegment :: Maybe Segment -> CxtValue -> [CxtValue] selectJSONMaybeSegment (Just seg) (cxt,val) = either (const []) (return . first (:cxt)) $ selectJSONSegment seg val selectJSONMaybeSegment Nothing cxtval = allSubValues cxtval -selectMultiJSON :: JSCxtValue -> JSMultiPath -> [JSCxtValue]+selectMultiJSON :: CxtValue -> MultiPath -> [CxtValue] selectMultiJSON cxtval [] = return cxtval selectMultiJSON cxtval (mp : ps) = selectJSONMaybeSegment mp cxtval >>= flip selectMultiJSON ps type Reader a = String -> (a, String) -readJSSegment :: Reader JSSegment+readJSSegment :: Reader Segment readJSSegment xs@('"':_) = case reads xs of -- TODO maybe we should use the JSON syntax for literal strings- [r] -> first JSObjectKey r+ [r] -> first ObjectKey r _ -> error "Parse error: malformed string (when reading path segment)" readJSSegment xs = case reads xs of- [r] -> first JSArrayIndex r+ [r] -> first ArrayIndex r _ -> error "Parse error: malformed integer (when reading path segment)" -readJSMultiSegment :: Reader (Maybe JSSegment)+readJSMultiSegment :: Reader (Maybe Segment) readJSMultiSegment ('*':xs) = (Nothing, xs) readJSMultiSegment xs = first Just . readJSSegment $ xs @@ -93,18 +96,18 @@ readJSPathGen r ('/':xs) = let (seg, ys) = r xs in seg : readJSPathGen r ys readJSPathGen _ (x:_) = error $ "Parse error: unexpected char "++show x++", '/' was expected" -readJSPath :: String -> JSPath+readJSPath :: String -> Path readJSPath = readJSPathGen readJSSegment -readJSMultiPath :: String -> JSMultiPath+readJSMultiPath :: String -> MultiPath readJSMultiPath = readJSPathGen readJSMultiSegment -showJSPath :: JSPath -> ShowS+showJSPath :: Path -> ShowS showJSPath = (('/':) .) . mconcat . intersperse ('/':) . map showJSSegment -showJSSegment :: JSSegment -> ShowS-showJSSegment (JSObjectKey f) = shows f-showJSSegment (JSArrayIndex ix) = shows ix+showJSSegment :: Segment -> ShowS+showJSSegment (ObjectKey f) = shows f+showJSSegment (ArrayIndex ix) = shows ix -- should already exists distrEitherPair :: (a, Either b c) -> Either (a, b) (a, c)@@ -127,15 +130,15 @@ main :: IO () main = do args <- getArgs- let pobj = either fail return . parseJSON =<< S.getContents+ let pobj = maybe (fail "JSON decoding") return . decode' =<< L.getContents case args of [] -> usage "Too few arguments" ["-m", path] -> do obj <- pobj- S.putStrLn . showJSON . JSArray . map snd . selectMultiJSON ([], obj) . readJSMultiPath $ path+ L8.putStrLn . encode . Array . V.fromList . map snd . selectMultiJSON ([], obj) . readJSMultiPath $ path [path] -> do obj <- pobj- either err (S.putStrLn . showJSON . snd) . distrEitherPair $ selectJSON ([], obj) (readJSPath path)+ either err (L8.putStrLn . encode . snd) . distrEitherPair $ selectJSON ([], obj) (readJSPath path) where err (cxt, msg) = hPutStrLn stderr $ (showString msg . showString "\nLocation in the structure: " . showJSPath (pathFromContext cxt)) "" _ -> usage "Too many arguments"
json-strings.hs view
@@ -1,22 +1,26 @@-import Text.JSON.AttoJSON-import qualified Data.ByteString as S+import Data.Aeson+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8 import Data.Monoid+import Data.Maybe import Data.Foldable hiding (mapM_) import Control.Monad (when) import System.IO (hPutStrLn, stderr) import System.Environment (getArgs) import System.Exit (exitFailure)+import qualified Data.Text as T+import qualified Data.Vector as V -- NOTE that the map keys are not included -jsonStrings :: JSValue -> [S.ByteString]+jsonStrings :: Value -> [T.Text] jsonStrings x0 = appEndo (go x0) []- where go (JSString s) = Endo (s:)- go (JSNumber _) = mempty- go (JSBool _) = mempty- go JSNull = mempty- go (JSObject m) = foldMap go m- go (JSArray xs) = foldMap go xs+ where go (String s) = Endo (s:)+ go (Number _) = mempty+ go (Bool _) = mempty+ go Null = mempty+ go (Object m) = foldMap go m+ go (Array xs) = foldMap go xs usage :: IO a usage = mapM_ (hPutStrLn stderr)@@ -30,9 +34,10 @@ main = do args <- getArgs when (not . null $ args) usage- S.putStrLn . showJSON -- printing the output- . JSArray . map JSString -- building the result+ L8.putStrLn . encode -- printing the output+ . Array . V.fromList -- building the result+ . map String -- building the elements . jsonStrings -- main processing- . either err id -- error handling- . parseJSON =<< S.getContents -- reading the input- where err = error . ("JSON parsing: "++)+ . fromMaybe err -- error handling+ . decode' =<< L.getContents -- reading the input+ where err = error "JSON parsing"
json-tools.cabal view
@@ -1,6 +1,6 @@ Name: json-tools Cabal-Version: >=1.6-Version: 0.3.1+Version: 0.4.0 License: BSD3 License-File: LICENSE Copyright: (c) Nicolas Pouillard@@ -14,34 +14,34 @@ executable json-concat main-is: json-concat.hs- Build-depends: base>=3&&<5, AttoJson, bytestring+ Build-depends: base>=3&&<5, aeson, bytestring ghc-options: -Wall -Odph executable json-deep-select-key main-is: json-deep-select-key.hs- Build-depends: base>=3&&<5, AttoJson, bytestring, containers+ Build-depends: base>=3&&<5, aeson, bytestring, containers ghc-options: -Wall -Odph executable json-select main-is: json-select.hs- Build-depends: base>=3&&<5, AttoJson, bytestring, containers+ Build-depends: base>=3&&<5, aeson, bytestring, containers ghc-options: -Wall -Odph executable json-iter main-is: json-iter.hs- Build-depends: base>=3&&<5, AttoJson, bytestring, process+ Build-depends: base>=3&&<5, aeson, bytestring, process Other-modules: Utils ghc-options: -Wall -Odph executable json-lines main-is: json-lines.hs- Build-depends: base>=3&&<5, AttoJson, bytestring+ Build-depends: base>=3&&<5, aeson, bytestring Other-modules: Utils ghc-options: -Wall -Odph executable json-strings main-is: json-strings.hs- Build-depends: base>=3&&<5, AttoJson, bytestring+ Build-depends: base>=3&&<5, aeson, bytestring ghc-options: -Wall -Odph executable json-unlines@@ -52,17 +52,23 @@ executable json-wrap main-is: json-wrap.hs- Build-depends: base>=3&&<5, AttoJson, bytestring+ Build-depends: base>=3&&<5, aeson, bytestring, vector ghc-options: -Wall -Odph executable json-xargs main-is: json-xargs.hs- Build-depends: base>=3&&<5, AttoJson, bytestring+ Build-depends: base>=3&&<5, aeson, bytestring ghc-options: -Wall -Odph executable tar2json main-is: tar2json.hs- Build-depends: base>=3&&<5, bytestring, convertible-text, data-object, data-object-json, tar+ Build-depends: base>=3&&<5, bytestring, aeson, unordered-containers,+ text, tar>=0.4.0+ ghc-options: -Wall -Odph++executable json-quote+ main-is: json-quote.hs+ Build-depends: base>=3&&<5, aeson, text ghc-options: -Wall -Odph source-repository head
json-unlines.hs view
@@ -4,7 +4,7 @@ import System.Environment (getArgs) import System.Exit (exitFailure) import System.IO (hPutStrLn,stderr)-import Utils (readFilesL)+import Utils (readFiles) usage :: IO a usage = mapM_ (hPutStrLn stderr)@@ -20,5 +20,5 @@ args <- getArgs when ("--help"`elem`args) usage L.putStrLn . L.cons '[' . L.intercalate "\n," . L.lines . L.concat- =<< readFilesL args+ =<< readFiles args L.putStrLn "]"
json-wrap.hs view
@@ -1,18 +1,22 @@ {-# LANGUAGE OverloadedStrings #-} import Data.List (intersperse)-import Data.Map (toList) import Data.Monoid-import Text.JSON.AttoJSON-import qualified Data.ByteString as S+import Data.Aeson+import Data.Maybe+import qualified Data.HashMap.Strict as HM+import qualified Data.Vector as V+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8 -- wrap, as in line-wrapping main :: IO ()-main = mapM_ S.putStr . ($["\n"]) . f . either err id . parseJSON =<< S.getContents- where f (JSArray a) = t"[" . cat (intersperse (t"\n,") (map (t . showJSON) a)) . t"]"- f (JSObject o) = t"{" . cat (intersperse (t"\n,") (map g . toList $ o)) . t"}"- f _ = error "impossible by decodeStrict post-condition"- g (key, val) = t key . t ":" . (t . showJSON) val- err s = error $ "JSON decoding: " ++ s- t x = (x:)- cat = appEndo . mconcat . map Endo+main = mapM_ L.putStr . ($["\n"]) . f . fromMaybe err . decode' =<< L.getContents+ where f (Array a) = t"[" . cat (intersperse (t"\n,") (map j . V.toList $ a)) . t"]"+ f (Object o) = t"{" . cat (intersperse (t"\n,") (map g . HM.toList $ o)) . t"}"+ f _ = error "impossible by decodeStrict post-condition"+ g (key, val) = t (encode key) . t(L8.pack ":") . j val+ j = t . encode+ err = error "JSON decoding"+ t x = (x:)+ cat = appEndo . mconcat . map Endo
json-xargs.hs view
@@ -1,6 +1,8 @@-import Text.JSON.AttoJSON-import qualified Data.ByteString.Char8 as S+import Data.Aeson+import qualified Data.ByteString.Lazy as L+import Data.Text as T import Data.Monoid+import Data.Maybe import Data.Foldable import Data.Functor import System.Environment@@ -9,20 +11,20 @@ -- NOTE that the map keys are not included -jsonArgs :: JSValue -> [String]+jsonArgs :: Value -> [String] jsonArgs x0 = appEndo (go x0) []- where go (JSString s) = f (S.unpack s)- go (JSNumber n) = f (show n)- go (JSBool b) = f (if b then "true" else "false")- go JSNull = f "null"- go (JSObject m) = foldMap go m- go (JSArray xs) = foldMap go xs+ where go (String s) = f (T.unpack s)+ go (Number n) = f (show n)+ go (Bool b) = f (if b then "true" else "false")+ go Null = f "null"+ go (Object m) = foldMap go m+ go (Array xs) = foldMap go xs f x = Endo (x:) main :: IO () main = do cmd:argv <- getArgs- args <- jsonArgs -- main processing- . either err id -- error handling- . parseJSON <$> S.getContents -- reading the input+ args <- jsonArgs -- main processing+ . fromMaybe err -- error handling+ . decode' <$> L.getContents -- reading the input exitWith =<< rawSystem cmd (argv ++ args)- where err = error . ("JSON parsing: "++)+ where err = error "Invalid JSON input"
tar2json.hs view
@@ -1,26 +1,26 @@ import Codec.Archive.Tar as Tar-import Data.Convertible.Base (convertSuccess)-import Data.Object-import Data.Object.Json as Json-import qualified Data.ByteString as S-import qualified Data.ByteString.Char8 as S8+import qualified Data.HashMap.Strict as HM+import qualified Data.Aeson as Aeson+import qualified Data.Text as T import qualified Data.ByteString.Lazy as L import System.IO -tar2json :: Tar.Entries -> JsonObject-tar2json es0 = Mapping [(k,v) | (k,Just v) <- entries es0] where+{-TODO currently does not work for binary files-} - entries :: Tar.Entries -> [(S.ByteString, Maybe JsonObject)]+tar2json :: Tar.Entries FormatError -> Aeson.Value+tar2json es0 = Aeson.Object $ HM.fromList [(k,v) | (k,Just v) <- entries es0] where++ entries :: Tar.Entries FormatError -> [(T.Text, Maybe Aeson.Value)] entries Done = []- entries (Fail s) = error s+ entries (Fail s) = error . show $ s entries (Next e es) = (path e, contents e) : entries es - path :: Tar.Entry -> S.ByteString- path = S8.pack {- Is this an encoding mistake? -} . entryPath+ path :: Tar.Entry -> T.Text+ path = T.pack . entryPath - contents :: Tar.Entry -> Maybe JsonObject- contents = fmap (Scalar . JsonString) . f . entryContent where- f (NormalFile s _) = Just (convertSuccess s)+ contents :: Tar.Entry -> Maybe Aeson.Value+ contents = fmap Aeson.toJSON . f . entryContent where+ f (NormalFile s _) = Just s f _ = Nothing main :: IO ()@@ -28,8 +28,8 @@ = do hPutStrLn stderr "Reading standard input..." hSetEncoding stdin latin1 hSetEncoding stdout latin1- S.putStr -- printing output- . Json.encode -- producing JSON+ L.putStr -- printing output+ . Aeson.encode -- producing JSON . tar2json -- main translation . Tar.read -- reading the archive =<< L.getContents -- reading the input