aeson-pretty-0.7/0000755000000000000000000000000012055475264012212 5ustar0000000000000000aeson-pretty-0.7/aeson-pretty.cabal0000644000000000000000000000411012055475264015624 0ustar0000000000000000name: aeson-pretty version: 0.7 license: BSD3 license-file: LICENSE category: Text, Web, JSON, Pretty Printer copyright: Copyright 2011 Falko Peters author: Falko Peters maintainer: Falko Peters stability: experimental cabal-version: >= 1.8 homepage: http://github.com/informatikr/aeson-pretty bug-reports: http://github.com/informatikr/aeson-pretty/issues build-type: Simple synopsis: JSON pretty-printing library and command-line tool. description: A JSON pretty-printing library compatible with aeson as well as a command-line tool to improve readabilty of streams of JSON data. . The /library/ provides the function "encodePretty". It is a drop-in replacement for aeson's "encode" function, producing JSON-ByteStrings for human readers. . The /command-line tool/ reads JSON from stdin and writes prettified JSON to stdout. It also offers a complementary "compact"-mode, essentially the opposite of pretty-printing. If you specify @-flib-only@ like this . > cabal install -flib-only aeson-pretty . the command-line tool will NOT be installed. extra-source-files: README.markdown flag lib-only description: Only build/install the library, NOT the command-line tool. default: False library exposed-modules: Data.Aeson.Encode.Pretty build-depends: aeson >= 0.6, base == 4.*, bytestring >= 0.9, vector >= 0.9, text >= 0.11, unordered-containers >= 0.1.3.0 ghc-options: -Wall executable aeson-pretty hs-source-dirs: cli-tool main-is: Main.hs if flag(lib-only) buildable: False else build-depends: aeson >= 0.6, aeson-pretty, attoparsec >= 0.10, base == 4.*, bytestring >= 0.9, cmdargs >= 0.7 ghc-options: -Wall ghc-prof-options: -auto-all source-repository head type: git location: http://github.com/informatikr/aeson-pretty aeson-pretty-0.7/LICENSE0000644000000000000000000000276112055475264013225 0ustar0000000000000000Copyright (c)2011, Falko Peters All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Falko Peters nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. aeson-pretty-0.7/README.markdown0000644000000000000000000000175012055475264014716 0ustar0000000000000000# Welcome to aeson-pretty This is a JSON pretty-printing Haskell library compatible with [aeson](http://hackage.haskell.org/package/aeson) as well as a command-line tool to improve readabilty of streams of JSON data. The **library** provides a single function `encodePretty`. It is a drop-in replacement for aeson's `encode` function, producing JSON-ByteStrings for human readers. The **command-line tool** reads JSON from stdin and writes prettified JSON to stdout. It also offers a complementary "compact"-mode, essentially the opposite of pretty-printing. # Join in! We are happy to receive bug reports, fixes, documentation enhancements, and other improvements. Please report bugs via the [github issue tracker](http://github.com/informatikr/aeson-pretty/issues). Master [git repository](http://github.com/informatikr/aeson-pretty): * `git clone git://github.com/informatikr/aeson-pretty.git` # Authors This library is written and maintained by Falko Peters, . aeson-pretty-0.7/Setup.hs0000644000000000000000000000005612055475264013647 0ustar0000000000000000import Distribution.Simple main = defaultMain aeson-pretty-0.7/cli-tool/0000755000000000000000000000000012055475264013734 5ustar0000000000000000aeson-pretty-0.7/cli-tool/Main.hs0000644000000000000000000000353612055475264015163 0ustar0000000000000000{-# LANGUAGE DeriveDataTypeable, RecordWildCards, OverloadedStrings #-} module Main (main) where import Prelude hiding (interact, concat, unlines, null) import Data.Aeson (Value(..), json', encode) import Data.Aeson.Encode.Pretty import Data.Attoparsec.Lazy (Result(..), parse) import Data.ByteString.Lazy.Char8 (ByteString, interact, unlines, null) import Data.Version (showVersion) import Paths_aeson_pretty (version) import System.Console.CmdArgs data Options = Opts { compact :: Bool , indent :: Int , sort :: Bool } deriving (Data, Typeable) opts :: Options opts = Opts { compact = False &= help "Compact output." , indent = 4 &= help "Number of spaces per nesting-level (default 4)." , sort = False &= help "Sort objects by key (default false)." } &= program prog &= summary smry &= details info where prog = "aeson-pretty" smry = prog++" "++showVersion version++": Pretty JSON, the easy way." info :: [String] info = [ "Read JSON from stdin and pretty-print to stdout. The complementary " , "compact-mode removes whitespace from the input." , "" , "(c) Falko Peters 2011" , "" , "License: BSD3, for details see the source-repository at" , "http://www.github.com/informatikr/aeson-pretty." , "" ] main :: IO () main = do Opts{..} <- cmdArgs opts let conf = Config { confIndent = indent , confCompare = if sort then compare else mempty } enc = if compact then encode else encodePretty' conf interact $ unlines . map enc . values values :: ByteString -> [Value] values s = case parse json' s of Done rest v -> v : values rest Fail rest _ _ | null rest -> [] | otherwise -> error "invalid json" aeson-pretty-0.7/Data/0000755000000000000000000000000012055475264013063 5ustar0000000000000000aeson-pretty-0.7/Data/Aeson/0000755000000000000000000000000012055475264014130 5ustar0000000000000000aeson-pretty-0.7/Data/Aeson/Encode/0000755000000000000000000000000012055475264015325 5ustar0000000000000000aeson-pretty-0.7/Data/Aeson/Encode/Pretty.hs0000644000000000000000000001155212055475264017154 0ustar0000000000000000{-# LANGUAGE OverloadedStrings, RecordWildCards #-} -- |Aeson-compatible pretty-printing of JSON 'Value's. module Data.Aeson.Encode.Pretty ( -- * Simple Pretty-Printing encodePretty, -- * Pretty-Printing with Configuration Options encodePretty', Config (..), defConfig, -- ** Sorting Keys in Objects -- |With the Aeson library, the order of keys in objects is undefined due -- objects being implemented as HashMaps. To allow user-specified key -- orders in the pretty-printed JSON, 'encodePretty'' can be configured -- with a comparison function. These comparison functions can be composed -- using the 'Monoid' interface. Some other useful helper functions to keep -- in mind are 'comparing' and 'on'. -- -- Consider the following deliberately convoluted example, demonstrating -- the use of comparison functions: -- -- An object might pretty-print as follows -- -- > { -- > "baz": ..., -- > "bar": ..., -- > "foo": ..., -- > "quux": ..., -- > } -- -- which is clearly a confusing order of keys. By using a comparison -- function such as -- -- > comp :: Text -> Text -> Ordering -- > comp = keyOrder ["foo","bar"] `mappend` comparing length -- -- we can achieve the desired neat result: -- -- > { -- > "foo": ..., -- > "bar": ..., -- > "baz": ..., -- > "quux": ..., -- > } -- mempty, -- |Serves as an order-preserving (non-)sort function. Re-exported from -- "Data.Monoid". compare, -- |Sort keys in their natural order, i.e. by comparing character codes. -- Re-exported from the Prelude and "Data.Ord" keyOrder ) where import Data.Aeson (Value(..), ToJSON(..)) import qualified Data.Aeson.Encode as Aeson import Data.ByteString.Lazy (ByteString) import Data.Function (on) import qualified Data.HashMap.Strict as H (toList) import Data.List (intersperse, sortBy, elemIndex) import Data.Maybe (fromMaybe) import Data.Monoid (mappend, mconcat, mempty) import Data.Ord import Data.Text (Text) import Data.Text.Lazy.Builder (Builder, toLazyText) import Data.Text.Lazy.Encoding (encodeUtf8) import qualified Data.Vector as V (toList) data PState = PState { pstIndent :: Int , pstLevel :: Int , pstSort :: [(Text, Value)] -> [(Text, Value)] } data Config = Config { confIndent :: Int -- ^ Indentation spaces per level of nesting , confCompare :: Text -> Text -> Ordering -- ^ Function used to sort keys in objects } -- |Sort keys by their order of appearance in the argument list. -- -- Keys that are not present in the argument list are considered to be greater -- than any key in the list and equal to all keys not in the list. I.e. keys -- not in the argument list are moved to the end, while their order is -- preserved. keyOrder :: [Text] -> Text -> Text -> Ordering keyOrder ks = comparing $ \k -> fromMaybe maxBound (elemIndex k ks) -- |The default configuration: indent by four spaces per level of nesting, do -- not sort objects by key. -- -- > defConfig = Config { confIndent = 4, confSort = mempty } defConfig :: Config defConfig = Config { confIndent = 4, confCompare = mempty } -- |A drop-in replacement for aeson's 'Aeson.encode' function, producing -- JSON-ByteStrings for human readers. -- -- Follows the default configuration in 'defConfig'. encodePretty :: ToJSON a => a -> ByteString encodePretty = encodePretty' defConfig -- |A variant of 'encodePretty' that takes an additional configuration -- parameter. encodePretty' :: ToJSON a => Config -> a -> ByteString encodePretty' Config{..} = encodeUtf8 . toLazyText . fromValue st . toJSON where st = PState confIndent 0 condSort condSort = sortBy (confCompare `on` fst) fromValue :: PState -> Value -> Builder fromValue st@PState{..} = go where go (Array v) = fromCompound st ("[","]") fromValue (V.toList v) go (Object m) = fromCompound st ("{","}") fromPair (pstSort (H.toList m)) go v = Aeson.fromValue v fromCompound :: PState -> (Builder, Builder) -> (PState -> a -> Builder) -> [a] -> Builder fromCompound st@PState{..} (delimL,delimR) fromItem items = mconcat [ delimL , if null items then mempty else "\n" <> items' <> "\n" <> fromIndent st , delimR ] where items' = mconcat . intersperse ",\n" $ map (\item -> fromIndent st' <> fromItem st' item) items st' = st { pstLevel = pstLevel + 1 } fromPair :: PState -> (Text, Value) -> Builder fromPair st (k,v) = Aeson.fromValue (toJSON k) <> ": " <> fromValue st v fromIndent :: PState -> Builder fromIndent PState{..} = mconcat $ replicate (pstIndent * pstLevel) " " (<>) :: Builder -> Builder -> Builder (<>) = mappend infixr 6 <>