drop incremental json object display; clean up code

This gets rid of quite a lot of ugly hacks around json generation.

I doubt that any real-world json parsers can parse incomplete objects, so
while it's not as nice to need to wait for the complete object, especially
for commands like `git annex info` that take a while, it doesn't seem worth
the added complexity.

This also causes the order of fields within the json objects to be
reordered. Since any real json parser shouldn't care, the only possible
problem would be with ad-hoc parsers of the old json output.
This commit is contained in:
Joey Hess 2016-09-09 18:13:55 -04:00
parent 61faf240d5
commit d7ea6a5684
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
6 changed files with 70 additions and 141 deletions

View file

@ -1,80 +0,0 @@
{- Streaming JSON output.
-
- Copyright 2011, 2016 Joey Hess <id@joeyh.name>
-
- License: BSD-2-clause
-}
{-# LANGUAGE GADTs, OverloadedStrings #-}
module Utility.JSONStream (
JSONChunk(..),
start,
add,
addNestedObject,
end
) where
import Data.Aeson
import qualified Data.Text as T
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.Lazy.UTF8 as BU8
import Data.Char
import Data.Word
data JSONChunk v where
AesonObject :: Object -> JSONChunk Object
JSONChunk :: ToJSON v => [(String, v)] -> JSONChunk [(String, v)]
encodeJSONChunk :: JSONChunk v -> B.ByteString
encodeJSONChunk (AesonObject o) = encode o
encodeJSONChunk (JSONChunk l) = encode $ object $ map mkPair l
where
mkPair (s, v) = (T.pack s, toJSON v)
{- Aeson does not support building up a larger JSON object piece by piece
- with streaming output. To support streaming, a hack:
- The final "}" is left off the JSON, allowing more chunks to be added
- to later. -}
start :: JSONChunk a -> B.ByteString
start a
| not (B.null b) && B.last b == endchar = B.init b
| otherwise = bad b
where
b = encodeJSONChunk a
add :: JSONChunk a -> B.ByteString
add a
| not (B.null b) && B.head b == startchar =
B.cons addchar (B.drop 1 b)
| otherwise = bad b
where
b = start a
addNestedObject :: String -> B.ByteString -> B.ByteString
addNestedObject s b = B.concat
[ ",\""
, BU8.fromString s
, "\":"
, b
, "}"
]
end :: B.ByteString
end = endchar `B.cons` sepchar `B.cons` B.empty
startchar :: Word8
startchar = fromIntegral (ord '{')
endchar :: Word8
endchar = fromIntegral (ord '}')
addchar :: Word8
addchar = fromIntegral (ord ',')
sepchar :: Word8
sepchar = fromIntegral (ord '\n')
bad :: B.ByteString -> a
bad b = error $ "JSON encoder generated unexpected value: " ++ show b