@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, OverloadedStrings #-}
1+{-# LANGUAGE CPP, BangPatterns, OverloadedStrings #-}
4-- Module: Data.Aeson.Encode
4-- Module: Data.Aeson.Encode
@@ -14,49 +14,74 @@
14-- Most frequently, you'll probably want to encode straight to UTF-8
14-- Most frequently, you'll probably want to encode straight to UTF-8
15-- (the standard JSON encoding) using 'encode'.
15-- (the standard JSON encoding) using 'encode'.
17−-- You can convert a 'Builder' (as returned by 'fromValue') to a
17+-- You can use the conversions to 'Builder's when embedding JSON messages as
18−-- string using e.g. 'toLazyText'.
18+-- parts of a protocol.
20module Data.Aeson.Encode
19module Data.Aeson.Encode
22+#if MIN_VERSION_bytestring(0,10,4)
23+ -- * Encoding to Builders
24+ , encodeToByteStringBuilder
25+ , encodeToTextBuilder
27+ -- * Encoding to Text Builders
28+ , encodeToTextBuilder
26−import Data.Aeson.Types (ToJSON(..), Value(..))
35+import Data.Aeson.Types (Value(..))
27import Data.Monoid (mappend)
36import Data.Monoid (mappend)
28import Data.Scientific (Scientific, coefficient, base10Exponent, scientificBuilder)
37import Data.Scientific (Scientific, coefficient, base10Exponent, scientificBuilder)
29import Data.Text.Lazy.Builder
38import Data.Text.Lazy.Builder
30import Data.Text.Lazy.Builder.Int (decimal)
39import Data.Text.Lazy.Builder.Int (decimal)
31−import Data.Text.Lazy.Encoding (encodeUtf8)
32import Numeric (showHex)
40import Numeric (showHex)
33−import qualified Data.ByteString.Lazy as L
34import qualified Data.HashMap.Strict as H
41import qualified Data.HashMap.Strict as H
35import qualified Data.Text as T
42import qualified Data.Text as T
36import qualified Data.Vector as V
43import qualified Data.Vector as V
38−-- | Encode a JSON value to a 'Builder'. You can convert this to a
45+#if MIN_VERSION_bytestring(0,10,4)
39−-- string using e.g. 'toLazyText', or encode straight to UTF-8 (the
46+import Data.Aeson.Encode.ByteString (encode, encodeToByteStringBuilder)
40−-- standard JSON encoding) using 'encode'.
47+#else
48+import Data.Aeson.Types (ToJSON(toJSON))
49+import qualified Data.ByteString.Lazy as BL
50+import qualified Data.Text.Lazy.Builder as TLB
51+import qualified Data.Text.Lazy.Encoding as TLE
53+-- | Encode a JSON 'Value' as a UTF-8 encoded 'BL.ByteString'.
54+encode :: ToJSON a => a -> BL.ByteString
55+encode = TLE.encodeUtf8 . TLB.toLazyText . encodeToTextBuilder . toJSON
58+-- | Encode a JSON 'Value' to a 'Builder', which can be embedded efficiently
59+-- in a text-based protocol.
60+encodeToTextBuilder :: Value -> Builder
64+ go Null = {-# SCC "go/Null" #-} "null"
65+ go (Bool b) = {-# SCC "go/Bool" #-} if b then "true" else "false"
66+ go (Number s) = {-# SCC "go/Number" #-} fromScientific s
67+ go (String s) = {-# SCC "go/String" #-} string s
69+ | V.null v = {-# SCC "go/Array" #-} "[]"
70+ | otherwise = {-# SCC "go/Array" #-}
72+ go (V.unsafeHead v) <>
73+ V.foldr f (singleton ']') (V.unsafeTail v)
74+ where f a z = singleton ',' <> go a <> z
75+ go (Object m) = {-# SCC "go/Object" #-}
77+ (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs
79+ where f a z = singleton ',' <> one a <> z
80+ one (k,v) = string k <> singleton ':' <> go v
82+{-# DEPRECATED fromValue "Use 'encodeToTextBuilder' instead" #-}
41fromValue :: Value -> Builder
83fromValue :: Value -> Builder
42−fromValue Null = {-# SCC "fromValue/Null" #-} "null"
84+fromValue = encodeToTextBuilder
43−fromValue (Bool b) = {-# SCC "fromValue/Bool" #-}
44− if b then "true" else "false"
45−fromValue (Number s) = {-# SCC "fromValue/Number" #-} fromScientific s
46−fromValue (String s) = {-# SCC "fromValue/String" #-} string s
48− | V.null v = {-# SCC "fromValue/Array" #-} "[]"
49− | otherwise = {-# SCC "fromValue/Array" #-}
51− fromValue (V.unsafeHead v) <>
52− V.foldr f (singleton ']') (V.unsafeTail v)
53− where f a z = singleton ',' <> fromValue a <> z
54−fromValue (Object m) = {-# SCC "fromValue/Object" #-}
56− (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs
58− where f a z = singleton ',' <> one a <> z
59− one (k,v) = string k <> singleton ':' <> fromValue v
61string :: T.Text -> Builder
86string :: T.Text -> Builder
62string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'
87string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'
@@ -93,12 +118,6 @@ fromScientific s
94 e = base10Exponent s
119 e = base10Exponent s
96−-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
97−encode :: ToJSON a => a -> L.ByteString
98−encode = {-# SCC "encode" #-} encodeUtf8 . toLazyText . fromValue .
99− {-# SCC "toJSON" #-} toJSON
100−{-# INLINE encode #-}
102(<>) :: Builder -> Builder -> Builder
121(<>) :: Builder -> Builder -> Builder
103(<>) = mappend
122(<>) = mappend
104{-# INLINE (<>) #-}
123{-# INLINE (<>) #-}