jsontsv 0.1.5.0 → 0.1.6.0
raw patch · 4 files changed
+66/−10 lines, 4 filesdep ~base
Dependency ranges changed: base
Files
- Main.hs +33/−7
- README.md +25/−1
- jsontsv.cabal +2/−2
- stack.yaml +6/−0
Main.hs view
@@ -9,10 +9,10 @@ import qualified Data.List import qualified Data.Text as T import qualified Data.Text.Lazy.IO as TL-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes, listToMaybe) import Control.Applicative import Control.Monad (when)-import Data.ByteString.Lazy as BL hiding (map, intersperse)+import qualified Data.ByteString.Lazy as BL hiding (map, intersperse) import qualified Data.ByteString.Lazy.Char8 as BS import Data.Attoparsec.Lazy as Atto hiding (Result) import Data.Attoparsec.ByteString.Char8 (endOfLine, sepBy)@@ -130,8 +130,20 @@ -- | KeyPath may have an alias for the header output data KeyPath = KeyPath [Key] (Maybe Text) deriving Show -data Key = Key Text | Index Int deriving (Eq, Show)+{-+ Key represents an object (HashMap) key.+ Index represents a position in an Array+ TupleKey represents a Text key in an array of pairs that should be treated + as a map. E.g.+ [["dinner","fish"],["dessert","pie"]]+ This is useful in the case of Data.Aeson emits pair tuples:+ [("dinner", "fish"),("dessert","pie")]+-}+data Key = Key Text + | Index Int + | TupleKey Text deriving (Eq, Show) + parseKeyPath :: Text -> [KeyPath] parseKeyPath s = case AT.parseOnly pKeyPaths s of Left err -> error $ "Parse error " ++ err @@ -154,12 +166,21 @@ Just <$> AT.takeWhile1 (AT.inClass "a-zA-Z0-9_-") pKeyOrIndex :: AT.Parser Key-pKeyOrIndex = pIndex <|> pKey+pKeyOrIndex = pTupleKey <|> pIndex <|> pKey -pKey = Key <$> AT.takeWhile1 (AT.notInClass " .[:")+pIndex :: AT.Parser Key +pIndex = Index <$> AT.decimal -pIndex = Index <$> AT.decimal <* AT.char ']'+pTupleKey :: AT.Parser Key+pTupleKey = do + AT.char '"' + xs <- AT.takeWhile1 (AT.notInClass "\"")+ AT.char '"'+ return $ TupleKey xs +pKey :: AT.Parser Key+pKey = Key <$> AT.takeWhile1 (AT.notInClass " .[:")+ evalToLineBuilder :: Config -> String -> [[Key]] -> Value -> B.Builder evalToLineBuilder config@Config{..} outDelim ks v = mconcat $ intersperse (B.fromText . T.pack $ outDelim) $ map (flip (evalToBuilder config) v) ks@@ -196,13 +217,18 @@ in case e of Just e' -> evalKeyPath config ks e' Nothing -> Null+evalKeyPath config (TupleKey k:ks) (Array v) = + -- array must be an array of 2-tuples+ let vs :: [(Value, Value)]+ vs = [(V.head tuple, tuple V.! 1) | Array tuple <- V.toList v , V.length tuple == 2]+ e = listToMaybe [v' | (String k', v') <- vs, k' == k]+ in maybe Null (evalKeyPath config ks) e -- traverse array elements with additional keys -- if key is _, e.g. cast._[0] , traverse INTO each array object -- e.g. "cast":[["Michael Caine",13473],["Demi Moore",65231],... evalKeyPath config@Config{..} (Key "_":ks) (Array v) = String . mconcat . intersperse arrayDelim $ map (evalToText config ks) (V.toList v) -- traverse array elements with additional keys- evalKeyPath _ ks@(Key key:_) (Array v) | V.null v = Null evalKeyPath config@Config{..} ks@(Key key:_) (Array v) = let vs = V.toList v
README.md view
@@ -86,12 +86,36 @@ with this expression - jsontsv -a '|' 'cast._[0]'+ jsontsv -a '|' 'id cast._[0]' < input This results in: 2 Michael Caine|Demi Moore +## Extracting 2-tuple values++From version 0.1.5.0, you can can access lists of pairs, e.g.++ {"menu":[["dinner","fish"],["dessert","pie"]]}++with the expression `["KEY"]`, e.g.:++ jsontsv 'menu["dinner"]'+ # => fish++ jsontsv 'menu["dessert"]'+ # => pie++ jsontsv 'menu["drink"]'+ # => null++This is useful because Data.Aeson emits Haskell 2-tuples in this format:++ ghci> encode [("dinner", "fish"),("dessert","pie")]+ "[[\"dinner\",\"fish\"],[\"dessert\",\"pie\"]]"++Moreover, encoding 2-tuples is often preferable to encoding `Data.Map.Map` because +encoding 2-tuples preserves ordering, whereas encoding `Map` does not. ## Installation
jsontsv.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/ name: jsontsv-version: 0.1.5.0+version: 0.1.6.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.@@ -17,7 +17,7 @@ executable jsontsv main-is: Main.hs- build-depends: base >=4.6 && <4.8+ build-depends: base >=4.6 && <4.9 , aeson >= 0.8.0.0 , bytestring , attoparsec >= 0.12.0.0
+ stack.yaml view
@@ -0,0 +1,6 @@+flags: {}+packages:+- '.'+extra-deps: +- string-qq-0.0.2+resolver: lts-3.0