packages feed

jsontsv 0.1.2.0 → 0.1.3.0

raw patch · 3 files changed

+42/−56 lines, 3 files

Files

Main.hs view
@@ -25,13 +25,14 @@ import qualified Options.Applicative as O import qualified Text.CSV as CSV -data Options = Options { jsonExpr :: String, outputMode :: OutputMode } deriving Show+data Options = Options { jsonExpr :: String, arrayDelim :: String, outputMode :: OutputMode } deriving Show  data OutputMode = TSVOutput { delimiter :: String } | CSVOutput deriving (Show)  parseOpts :: O.Parser Options parseOpts = Options    <$> O.argument O.str (O.metavar "FIELDS")+  <*> O.strOption (O.metavar "ARRAY-DELIM" <> O.value "," <> O.short 'a' <> O.help "concatentated array elem delimiter. Default to comma")   <*> ((O.flag' CSVOutput (O.short 'c' <> O.long "csv" <> O.help "output CSV"))        <|> (TSVOutput <$> (O.strOption (O.metavar "DELIM" <> O.value "\t" <> O.short 'd' <> O.help "output field delimiter. Defaults to tab")))) @@ -39,15 +40,16 @@           (O.fullDesc <> O.progDesc "Transform JSON objects to TSV" <> O.header "jsontsv")  main = do-  Options expr mode <- O.execParser opts+  Options expr arrayDelim mode <- O.execParser opts   x <- BL.getContents    let xs :: [Value]       xs = decodeStream x-  let ks' = parseKeyPath $ T.pack expr+      ks' = parseKeyPath $ T.pack expr+      arrayDelim' = T.pack arrayDelim   -- Prelude.putStrLn $ "key Paths " ++ show ks'   case mode of -    TSVOutput delim -> mapM_ (TL.putStrLn . B.toLazyText . evalToLineBuilder delim ks') xs-    CSVOutput -> Prelude.putStrLn . CSV.printCSV $ map (map T.unpack . evalToList ks') $  xs+    TSVOutput delim -> mapM_ (TL.putStrLn . B.toLazyText . evalToLineBuilder arrayDelim' delim ks') xs+    CSVOutput -> Prelude.putStrLn . CSV.printCSV $ map (map T.unpack . evalToList arrayDelim' ks') $  xs  decodeStream :: (FromJSON a) => BL.ByteString -> [a] decodeStream bs = case decodeWith json bs of@@ -86,44 +88,47 @@ type KeyPath = [Key] data Key = Key Text | Index Int deriving (Eq, Show) -evalToLineBuilder :: String -> [KeyPath] -> Value -> B.Builder -evalToLineBuilder delim ks v = mconcat $ intersperse (B.fromText . T.pack $ delim) $  map (flip evalToBuilder v) ks+evalToLineBuilder :: Text -> String -> [KeyPath] -> Value -> B.Builder +evalToLineBuilder arrayDelim delim ks v = +    mconcat $ intersperse (B.fromText . T.pack $ delim) $  map (flip (evalToBuilder arrayDelim) v) ks -evalToList :: [KeyPath] -> Value -> [Text]-evalToList ks v = map (flip evalToText v) ks+type ArrayDelimiter = Text -evalToBuilder :: KeyPath -> Value -> B.Builder-evalToBuilder k v = valToBuilder $ evalKeyPath k v+evalToList :: Text -> [KeyPath] -> Value -> [Text]+evalToList arrayDelim ks v = map (flip (evalToText arrayDelim) v) ks -evalToText :: KeyPath -> Value -> Text-evalToText k v = valToText $ evalKeyPath k v+evalToBuilder :: ArrayDelimiter -> KeyPath -> Value -> B.Builder+evalToBuilder d k v = valToBuilder $ evalKeyPath d k v +evalToText :: ArrayDelimiter -> KeyPath -> Value -> Text+evalToText d k v = valToText $ evalKeyPath d k v+ -- evaluates the a JS key path against a Value context to a leaf Value-evalKeyPath :: KeyPath -> Value -> Value-evalKeyPath [] x@(String _) = x-evalKeyPath [] x@Null = x-evalKeyPath [] x@(Number _) = x-evalKeyPath [] x@(Bool _) = x-evalKeyPath [] x@(Object _) = x-evalKeyPath [] x@(Array v) = +evalKeyPath :: ArrayDelimiter -> KeyPath -> Value -> Value+evalKeyPath d [] x@(String _) = x+evalKeyPath d [] x@Null = x+evalKeyPath d [] x@(Number _) = x+evalKeyPath d [] x@(Bool _) = x+evalKeyPath d [] x@(Object _) = x+evalKeyPath d [] x@(Array v) =            let vs = V.toList v-              xs = intersperse "," $ map (evalToText []) vs+              xs = intersperse d $ map (evalToText d []) vs           in String . mconcat $ xs-evalKeyPath (Key key:ks) (Object s) = +evalKeyPath d (Key key:ks) (Object s) =      case (HM.lookup key s) of-        Just x          -> evalKeyPath ks x+        Just x          -> evalKeyPath d ks x         Nothing -> Null-evalKeyPath (Index idx:ks) (Array v) = +evalKeyPath d (Index idx:ks) (Array v) =        let e = (V.!?) v idx       in case e of -        Just e' -> evalKeyPath ks e'+        Just e' -> evalKeyPath d ks e'         Nothing -> Null -- traverse array elements with additional keys-evalKeyPath ks@(Key key:_) (Array v) = +evalKeyPath d ks@(Key key:_) (Array v) =        let vs = V.toList v-      in String . mconcat . intersperse "," $ map (evalToText ks) vs-evalKeyPath ((Index _):_) _ = Null-evalKeyPath _ _ = Null+      in String . mconcat . intersperse d $ map (evalToText d ks) vs+evalKeyPath _ ((Index _):_) _ = Null+evalKeyPath _ _ _ = Null  valToBuilder :: Value -> B.Builder valToBuilder (String x) = B.fromText x
README.md view
@@ -14,28 +14,6 @@   "title": "Terminator 2: Judgement Day",   "year": 1991,   "stars": [-    "Arnold Schwarzenegger",-    "Linda Hamilton"-  ],-  "ratings": {-    "imdb": 8.5-  }-}-{-  "title": "Interstellar",-  "year": 2014,-  "stars": [-    "Matthew McConaughey",-    "Anne Hathaway"-  ],-  "ratings": {-    "imdb": 8.9-  }-}-{-  "title": "Terminator 2: Judgement Day",-  "year": 1991,-  "stars": [     {       "name": "Arnold Schwarzenegger"     },@@ -102,11 +80,12 @@ ``` jsontsv -Usage: jsontsv FIELDS ([-c|--csv] | [-d DELIM])+Usage: jsontsv FIELDS [-a ARRAY-DELIM] ([-c|--csv] | [-d DELIM])   Transform JSON objects to TSV  Available options:   -h,--help                Show this help text+  -a ARRAY-DELIM           concatentated array element delimiter. Defaults to comma   -c,--csv                 output CSV   -d DELIM                 output field delimiter. Defaults to tab ```@@ -139,7 +118,8 @@ * Strings and numbers are copied to output. * Boolean values are output as `t` or `f`. * null is printed as `null`-* If the leaf value is an array, it is concatenated into a single comma-separated string+* If the leaf value is an array, it is concatenated into a single+  comma-separated string. The delimiter can be changed with the `-a` option.  ## Performing post-processing on field values @@ -147,6 +127,7 @@  ## Known alternatives  -* [jsawk](https://github.com/micha/jsawk) +* [jsawk](https://github.com/micha/jsawk) Jsawk is like awk, but for JSON. (nodejs) * [jq][jq]-* [jsoncsv](https://github.com/gradus/jsoncsv)+* [jsoncsv](https://github.com/gradus/jsoncsv) a json to csv library in javascript/coffeescript+* [json](https://github.com/konklone/json) A free, in-browser JSON to CSV converter.
jsontsv.cabal view
@@ -2,7 +2,7 @@ --  see http://haskell.org/cabal/users-guide/  name:                jsontsv-version:             0.1.2.0+version:             0.1.3.0 synopsis:            JSON to TSV transformer homepage:            https://github.com/danchoi/jsontsv description:         Transforms JSON into tab-separated line-oriented output, for easier processing in Unix-style pipelines.