1{-# LANGUAGE DeriveDataTypeable, RecordWildCards, OverloadedStrings #-} 2module Main (main) where 3 4import Prelude hiding (interact, concat, unlines, null) 5import Data.Aeson (Value(..), json', encode) 6import Data.Aeson.Encode.Pretty 7import Data.Attoparsec.Lazy (Result(..), parse) 8import Data.ByteString.Lazy.Char8 (ByteString, interact, unlines, null) 9import Data.Version (showVersion) 10import Paths_aeson_pretty (version) 11import System.Console.CmdArgs 12 13 14data Options = Opts { compact :: Bool 15 , indent :: Int 16 , sort :: Bool 17 } 18 deriving (Data, Typeable) 19 20opts :: Options 21opts = Opts 22 { compact = False &= help "Compact output." 23 , indent = 4 &= help "Number of spaces per nesting-level (default 4)." 24 , sort = False &= help "Sort objects by key (default: undefined order)." 25 } &= program prog 26 &= summary smry 27 &= details info 28 where 29 prog = "aeson-pretty" 30 smry = prog++" "++showVersion version++": Pretty JSON, the easy way." 31 32info :: [String] 33info = 34 [ "Read JSON from stdin and pretty-print to stdout. The complementary " 35 , "compact-mode removes whitespace from the input." 36 , "" 37 , "(c) Falko Peters 2011" 38 , "" 39 , "License: BSD3, for details see the source-repository at" 40 , "http://www.github.com/informatikr/aeson-pretty." 41 , "" 42 ] 43 44main :: IO () 45main = do 46 Opts{..} <- cmdArgs opts 47 let conf = Config { confIndent = Spaces indent 48 , confCompare = if sort then compare else mempty 49 , confNumFormat = Generic 50 , confTrailingNewline = False 51 } 52 enc = if compact then encode else encodePretty' conf 53 interact $ unlines . map enc . values 54 55values :: ByteString -> [Value] 56values s = case parse json' s of 57 Done rest v -> v : values rest 58 Fail rest _ _ 59 | null rest -> [] 60 | otherwise -> error "invalid json" 61