jsontsv 0.1.3.1 → 0.1.4.0
raw patch · 4 files changed
+44/−34 lines, 4 filesdep ~attoparsecdep ~csvdep ~text
Dependency ranges changed: attoparsec, csv, text
Files
- Main.hs +22/−9
- README.md +17/−20
- example.json +1/−1
- jsontsv.cabal +4/−4
Main.hs view
@@ -6,10 +6,12 @@ import Data.Text (Text) import qualified Data.Text.Encoding as T (decodeUtf8) import Data.List (intersperse)+import qualified Data.List import qualified Data.Text as T import qualified Data.Text.Lazy.IO as TL import Data.Maybe (catMaybes) import Control.Applicative+import Control.Monad (when) import Data.ByteString.Lazy as BL hiding (map, intersperse) import qualified Data.ByteString.Lazy.Char8 as BS import Data.Attoparsec.Lazy as Atto hiding (Result)@@ -25,31 +27,42 @@ import qualified Options.Applicative as O import qualified Text.CSV as CSV -data Options = Options { jsonExpr :: String, arrayDelim :: String, outputMode :: OutputMode } deriving Show+data Options = Options { jsonExpr :: String, arrayDelim :: String, outputMode :: OutputMode, showHeader :: Bool } 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 "STRING" <> 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 "STRING" <> O.value "\t" <> O.short 'd' <> O.help "output field delimiter. Defaults to tab"))))+ <*> O.strOption (O.metavar "STRING" <> O.value "," <> O.short 'a' <> O.help "Concatentated array elem delimiter. Defaults to comma.")+ <*> (parseCSVMode <|> parseTSVMode)+ <*> O.flag False True (O.short 'H' <> O.help "Include headers") +parseCSVMode = O.flag' CSVOutput (O.short 'c' <> O.long "csv" <> O.help "Output CSV")++parseTSVMode = TSVOutput + <$> (O.strOption + (O.metavar "STRING" <> O.value "\t" <> O.short 'd' <> O.help "Output field delimiter. Defaults to tab."))+ opts = O.info (O.helper <*> parseOpts) (O.fullDesc <> O.progDesc "Transform JSON objects to TSV" <> O.header "jsontsv") main = do- Options expr arrayDelim mode <- O.execParser opts+ Options expr arrayDelim mode showHeaders <- O.execParser opts x <- BL.getContents let xs :: [Value] xs = decodeStream x- ks' = parseKeyPath $ T.pack expr+ ks = parseKeyPath $ T.pack expr arrayDelim' = T.pack arrayDelim- -- Prelude.putStrLn $ "key Paths " ++ show ks'+ -- Prelude.putStrLn $ "key Paths " ++ show ks+ when showHeaders $ do+ let hs = words expr+ case mode of + TSVOutput delim -> Prelude.putStrLn . Data.List.intercalate delim $ hs+ CSVOutput -> Prelude.putStrLn . CSV.printCSV $ [hs] case mode of - 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+ 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
README.md view
@@ -1,17 +1,17 @@ # jsontsv -Transforms JSON objects into tab-separated line-oriented output, which is more-convenient for downstream processing with Unix tools like `grep`, `awk`,-`diff`, etc., and for inspecting with spreadsheet programs using a CSV output-option.+Transforms JSON objects into delimiter-separated line-oriented output, which is+more convenient for downstream processing with Unix tools like `grep`, `awk`,+`diff`, etc. Also useful for converting JSON data into spreadsheet data. CSV-style+output is also supported. ## Synopsis -input.json:+input: ```json {- "title": "Terminator 2: Judgement Day",+ "title": "Terminator 2: Judgment Day", "year": 1991, "stars": [ {@@ -45,23 +45,23 @@ Note that this input is not actually JSON at the top-level. It is a stream of JSON objects. It can be fed into `jsontsv`: - jsontsv 'title year stars.name ratings.imdb' < input.json+ jsontsv 'title year stars.name ratings.imdb' < input outputs this tab-separated text: ```tsv-Terminator 2: Judgement Day 1991 Arnold Schwarzenegger,Linda Hamilton 8.5+Terminator 2: Judgment Day 1991 Arnold Schwarzenegger,Linda Hamilton 8.5 Interstellar 2014 Matthew McConaughey,Anne Hathaway 8.9 ``` You can pick off array elements using `[i]` syntax: - jsontsv 'title year stars[0].name' < input.json+ jsontsv 'title year stars[0].name' < input outputs ```tsv-Terminator 2: Judgement Day 1991 Arnold Schwarzenegger+Terminator 2: Judgment Day 1991 Arnold Schwarzenegger Interstellar 2014 Matthew McConaughey ``` @@ -80,14 +80,15 @@ ``` jsontsv -Usage: jsontsv FIELDS [-a STRING] ([-c|--csv] | [-d STRING])+Usage: jsontsv FIELDS [-a STRING] ([-c|--csv] | [-d STRING]) [-H] Transform JSON objects to TSV Available options: -h,--help Show this help text- -a STRING concatentated array elem delimiter. Default to comma- -c,--csv output CSV- -d STRING output field delimiter. Defaults to tab+ -a STRING Concatentated array elem delimiter. Defaults to comma.+ -c,--csv Output CSV+ -d STRING Output field delimiter. Defaults to tab.+ -H Include headers ``` Input should be a stream of JSON objects of the same or mostly similar shape,@@ -97,7 +98,7 @@ [jq]:http://stedolan.github.io/jq/ - curl -s "https://api.github.com/users/danchoi/repos?type=owner&sort=created&direction=desc" \+ curl -s "https://api.github.com/users/danchoi/repos?sort=created&direction=desc" \ | jq '.[]' | jsontsv 'id name stargazers_count open_issues_count' outputs@@ -119,11 +120,7 @@ * 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. The delimiter can be changed with the `-a` option.--## Performing post-processing on field values--Use awk!+ comma-separated string. This delimiter can be changed with the `-a` option. ## Known alternatives
example.json view
@@ -1,5 +1,5 @@ {- "title": "Terminator 2: Judgement Day",+ "title": "Terminator 2: Judgment Day", "year": 1991, "stars": [ {"name": "Arnold Schwarzenegger"},
jsontsv.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/ name: jsontsv-version: 0.1.3.1+version: 0.1.4.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.@@ -20,12 +20,12 @@ build-depends: base >=4.7 && <4.8 , aeson >= 0.8.0.0 , bytestring- , attoparsec >= 0.12.1.0+ , attoparsec >= 0.12.0.0 , containers , unordered-containers- , text >= 1.2.0.0+ , text >= 1.0.0.0 , vector , scientific , optparse-applicative- , csv >= 0.1.2+ , csv >= 0.1.0 default-language: Haskell2010