aeson 0.6.2.1 → 0.7.0.0
raw patch · 24 files changed
+1466/−1070 lines, 24 filesdep +HUnitdep +scientificdep +test-framework-hunitdep ~attoparsecdep ~bytestringdep ~template-haskell
Dependencies added: HUnit, scientific, test-framework-hunit
Dependency ranges changed: attoparsec, bytestring, template-haskell, text, time
Files
- Data/Aeson/Encode.hs +63/−44
- Data/Aeson/Encode/ByteString.hs +116/−0
- Data/Aeson/Functions.hs +0/−20
- Data/Aeson/Generic.hs +1/−16
- Data/Aeson/Parser/Internal.hs +125/−81
- Data/Aeson/Types.hs +2/−1
- Data/Aeson/Types/Class.hs +2/−704
- Data/Aeson/Types/Generic.hs +1/−1
- Data/Aeson/Types/Instances.hs +795/−0
- Data/Aeson/Types/Internal.hs +59/−15
- aeson.cabal +54/−48
- benchmarks/AesonEncode.hs +7/−3
- benchmarks/AesonParse.hs +4/−3
- benchmarks/CompareWithJSON.hs +22/−2
- benchmarks/JsonParse.hs +2/−2
- benchmarks/aeson-benchmarks.cabal +6/−5
- benchmarks/bench-parse.py +3/−2
- benchmarks/encode.py +11/−1
- benchmarks/json-data/geometry.json +1/−0
- benchmarks/parse.py +11/−1
- changelog +119/−0
- release-notes.markdown +0/−113
- tests/Instances.hs +2/−1
- tests/Properties.hs +60/−7
Data/Aeson/Encode.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE CPP, BangPatterns, OverloadedStrings #-} -- | -- Module: Data.Aeson.Encode@@ -14,50 +14,74 @@ -- Most frequently, you'll probably want to encode straight to UTF-8 -- (the standard JSON encoding) using 'encode'. ----- You can convert a 'Builder' (as returned by 'fromValue') to a--- string using e.g. 'toLazyText'.-+-- You can use the conversions to 'Builder's when embedding JSON messages as+-- parts of a protocol. module Data.Aeson.Encode- (- fromValue- , encode+ ( encode++#if MIN_VERSION_bytestring(0,10,4)+ -- * Encoding to Builders+ , encodeToByteStringBuilder+ , encodeToTextBuilder+#else+ -- * Encoding to Text Builders+ , encodeToTextBuilder+#endif++ -- * Deprecated+ , fromValue ) where -import Data.Aeson.Types (ToJSON(..), Value(..))-import Data.Attoparsec.Number (Number(..))+import Data.Aeson.Types (Value(..)) import Data.Monoid (mappend)+import Data.Scientific (Scientific, coefficient, base10Exponent, scientificBuilder) import Data.Text.Lazy.Builder import Data.Text.Lazy.Builder.Int (decimal)-import Data.Text.Lazy.Builder.RealFloat (realFloat)-import Data.Text.Lazy.Encoding (encodeUtf8) import Numeric (showHex)-import qualified Data.ByteString.Lazy as L import qualified Data.HashMap.Strict as H import qualified Data.Text as T import qualified Data.Vector as V --- | Encode a JSON value to a 'Builder'. You can convert this to a--- string using e.g. 'toLazyText', or encode straight to UTF-8 (the--- standard JSON encoding) using 'encode'.+#if MIN_VERSION_bytestring(0,10,4)+import Data.Aeson.Encode.ByteString (encode, encodeToByteStringBuilder)+#else+import Data.Aeson.Types (ToJSON(toJSON))+import qualified Data.ByteString.Lazy as BL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.Encoding as TLE++-- | Encode a JSON 'Value' as a UTF-8 encoded 'BL.ByteString'.+encode :: ToJSON a => a -> BL.ByteString+encode = TLE.encodeUtf8 . TLB.toLazyText . encodeToTextBuilder . toJSON+#endif++-- | Encode a JSON 'Value' to a 'Builder', which can be embedded efficiently+-- in a text-based protocol.+encodeToTextBuilder :: Value -> Builder+encodeToTextBuilder =+ go+ where+ go Null = {-# SCC "go/Null" #-} "null"+ go (Bool b) = {-# SCC "go/Bool" #-} if b then "true" else "false"+ go (Number s) = {-# SCC "go/Number" #-} fromScientific s+ go (String s) = {-# SCC "go/String" #-} string s+ go (Array v)+ | V.null v = {-# SCC "go/Array" #-} "[]"+ | otherwise = {-# SCC "go/Array" #-}+ singleton '[' <>+ go (V.unsafeHead v) <>+ V.foldr f (singleton ']') (V.unsafeTail v)+ where f a z = singleton ',' <> go a <> z+ go (Object m) = {-# SCC "go/Object" #-}+ case H.toList m of+ (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs+ _ -> "{}"+ where f a z = singleton ',' <> one a <> z+ one (k,v) = string k <> singleton ':' <> go v++{-# DEPRECATED fromValue "Use 'encodeToTextBuilder' instead" #-} fromValue :: Value -> Builder-fromValue Null = {-# SCC "fromValue/Null" #-} "null"-fromValue (Bool b) = {-# SCC "fromValue/Bool" #-}- if b then "true" else "false"-fromValue (Number n) = {-# SCC "fromValue/Number" #-} fromNumber n-fromValue (String s) = {-# SCC "fromValue/String" #-} string s-fromValue (Array v)- | V.null v = {-# SCC "fromValue/Array" #-} "[]"- | otherwise = {-# SCC "fromValue/Array" #-}- singleton '[' <>- fromValue (V.unsafeHead v) <>- V.foldr f (singleton ']') (V.unsafeTail v)- where f a z = singleton ',' <> fromValue a <> z-fromValue (Object m) = {-# SCC "fromValue/Object" #-}- case H.toList m of- (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs- _ -> "{}"- where f a z = singleton ',' <> one a <> z- one (k,v) = string k <> singleton ':' <> fromValue v+fromValue = encodeToTextBuilder string :: T.Text -> Builder string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'@@ -87,17 +111,12 @@ | otherwise = singleton c where h = showHex (fromEnum c) "" -fromNumber :: Number -> Builder-fromNumber (I i) = decimal i-fromNumber (D d)- | isNaN d || isInfinite d = "null"- | otherwise = realFloat d---- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.-encode :: ToJSON a => a -> L.ByteString-encode = {-# SCC "encode" #-} encodeUtf8 . toLazyText . fromValue .- {-# SCC "toJSON" #-} toJSON-{-# INLINE encode #-}+fromScientific :: Scientific -> Builder+fromScientific s+ | e < 0 = scientificBuilder s+ | otherwise = decimal (coefficient s * 10 ^ e)+ where+ e = base10Exponent s (<>) :: Builder -> Builder -> Builder (<>) = mappend
+ Data/Aeson/Encode/ByteString.hs view
@@ -0,0 +1,116 @@+{-# LANGUAGE BangPatterns, OverloadedStrings #-}++-- |+-- Module: Data.Aeson.EncodeUtf8+-- Copyright: (c) 2011 MailRank, Inc.+-- (c) 2013 Simon Meier <iridcode@gmail.com>+-- License: Apache+-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>+-- Stability: experimental+-- Portability: portable+--+-- Efficiently serialize a JSON value using the UTF-8 encoding.++module Data.Aeson.Encode.ByteString+ ( encode+ , encodeToByteStringBuilder+ ) where++import Prelude hiding (null)+import Data.Aeson.Types (ToJSON(..), Value(..))+import Data.Char (ord)+import Data.Scientific (Scientific, coefficient, base10Exponent, formatScientific, FPFormat(Generic))+import Data.Word (Word8)+import Data.Monoid (mappend)+import Data.ByteString.Builder as B+import Data.ByteString.Builder.Prim as BP+import qualified Data.ByteString.Lazy as L+import qualified Data.HashMap.Strict as HMS+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import qualified Data.Vector as V++(<>) :: Builder -> Builder -> Builder+(<>) = mappend+{-# INLINE (<>) #-}+infixr 6 <>++-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.+encode :: ToJSON a => a -> L.ByteString+encode = B.toLazyByteString . encodeToByteStringBuilder . toJSON++-- | Encode a JSON value to a ByteString 'B.Builder'. Use this function if you+-- must prepend or append further bytes to the encoded JSON value.+encodeToByteStringBuilder :: Value -> Builder+encodeToByteStringBuilder Null = null+encodeToByteStringBuilder (Bool b) = bool b+encodeToByteStringBuilder (Number n) = number n+encodeToByteStringBuilder (String s) = string s+encodeToByteStringBuilder (Array v) = array v+encodeToByteStringBuilder (Object m) = object m++null :: Builder+null = BP.primBounded (ascii4 ('n',('u',('l','l')))) ()++bool :: Bool -> Builder+bool = BP.primBounded (BP.condB id (ascii4 ('t',('r',('u','e'))))+ (ascii5 ('f',('a',('l',('s','e'))))))++array :: V.Vector Value -> Builder+array v+ | V.null v = B.char8 '[' <> B.char8 ']'+ | otherwise = B.char8 '[' <>+ encodeToByteStringBuilder (V.unsafeHead v) <>+ V.foldr withComma (B.char8 ']') (V.unsafeTail v)+ where+ withComma a z = B.char8 ',' <> encodeToByteStringBuilder a <> z++object :: HMS.HashMap T.Text Value -> Builder+object m = case HMS.toList m of+ (x:xs) -> B.char8 '{' <> one x <> foldr withComma (B.char8 '}') xs+ _ -> B.char8 '{' <> B.char8 '}'+ where+ withComma a z = B.char8 ',' <> one a <> z+ one (k,v) = string k <> B.char8 ':' <> encodeToByteStringBuilder v++string :: T.Text -> B.Builder+string t =+ B.char8 '"' <> TE.encodeUtf8BuilderEscaped escapeAscii t <> B.char8 '"'+ where+ escapeAscii :: BP.BoundedPrim Word8+ escapeAscii =+ BP.condB (== c2w '\\' ) (ascii2 ('\\','\\')) $+ BP.condB (== c2w '\"' ) (ascii2 ('\\','"' )) $+ BP.condB (>= c2w '\x20') (BP.liftFixedToBounded BP.word8) $+ BP.condB (== c2w '\n' ) (ascii2 ('\\','n' )) $+ BP.condB (== c2w '\r' ) (ascii2 ('\\','r' )) $+ BP.condB (== c2w '\t' ) (ascii2 ('\\','t' )) $+ (BP.liftFixedToBounded hexEscape) -- fallback for chars < 0x20++ c2w = fromIntegral . ord++ hexEscape :: BP.FixedPrim Word8+ hexEscape = (\c -> ('\\', ('u', fromIntegral c))) BP.>$<+ BP.char8 BP.>*< BP.char8 BP.>*< BP.word16HexFixed++number :: Scientific -> Builder+number s+ | e < 0 = B.string8 $ formatScientific Generic Nothing s+ | otherwise = B.integerDec (coefficient s * 10 ^ e)+ where+ e = base10Exponent s+++{-# INLINE ascii2 #-}+ascii2 :: (Char, Char) -> BP.BoundedPrim a+ascii2 cs = BP.liftFixedToBounded $ (const cs) BP.>$< BP.char7 BP.>*< BP.char7++{-# INLINE ascii4 #-}+ascii4 :: (Char, (Char, (Char, Char))) -> BP.BoundedPrim a+ascii4 cs = BP.liftFixedToBounded $ (const cs) >$<+ BP.char7 BP.>*< BP.char7 BP.>*< BP.char7 BP.>*< BP.char7++{-# INLINE ascii5 #-}+ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BP.BoundedPrim a+ascii5 cs = BP.liftFixedToBounded $ (const cs) >$<+ BP.char7 BP.>*< BP.char7 BP.>*< BP.char7 BP.>*< BP.char7 BP.>*< BP.char7
Data/Aeson/Functions.hs view
@@ -12,17 +12,9 @@ , hashMapKey , mapKeyVal , mapKey- -- * String conversions- , decode- , strict- , lazy ) where import Data.Hashable (Hashable)-import Data.Text (Text)-import Data.Text.Encoding (decodeUtf8, encodeUtf8)-import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as L import qualified Data.HashMap.Strict as H import qualified Data.Map as M @@ -48,15 +40,3 @@ mapKey :: (Eq k2, Hashable k2) => (k1 -> k2) -> H.HashMap k1 v -> H.HashMap k2 v mapKey fk = mapKeyVal fk id {-# INLINE mapKey #-}--strict :: L.ByteString -> Text-strict = decode . B.concat . L.toChunks-{-# INLINE strict #-}--lazy :: Text -> L.ByteString-lazy = L.fromChunks . (:[]) . encodeUtf8-{-# INLINE lazy #-}--decode :: B.ByteString -> Text-decode = decodeUtf8-{-# INLINE decode #-}
Data/Aeson/Generic.hs view
@@ -30,7 +30,7 @@ import Control.Applicative ((<$>)) import Control.Arrow (first) import Control.Monad.State.Strict-import Data.Aeson.Functions hiding (decode)+import Data.Aeson.Functions import Data.Aeson.Types hiding (FromJSON(..), ToJSON(..), fromJSON) import Data.Attoparsec.Number (Number) import Data.Generics@@ -39,14 +39,11 @@ import Data.IntSet (IntSet) import Data.Maybe (fromJust) import Data.Text (Text, pack, unpack)-import Data.Text.Encoding (encodeUtf8) import Data.Time.Clock (UTCTime) import Data.Word (Word, Word8, Word16, Word32, Word64) import Data.Aeson.Parser.Internal (decodeWith, json, json') import qualified Data.Aeson.Encode as E-import qualified Data.Aeson.Functions as F import qualified Data.Aeson.Types as T-import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import qualified Data.HashMap.Strict as H import qualified Data.Map as Map@@ -111,8 +108,6 @@ `extQ` (T.toJSON :: T Text) `extQ` (T.toJSON :: T LT.Text) `extQ` (T.toJSON :: T String)- `extQ` (T.toJSON :: T B.ByteString)- `extQ` (T.toJSON :: T L.ByteString) `extQ` (T.toJSON :: T T.Value) `extQ` (T.toJSON :: T DotNetTime) `extQ` (T.toJSON :: T UTCTime)@@ -129,8 +124,6 @@ | tyrep == typeOf DT.empty = remap id | tyrep == typeOf LT.empty = remap LT.toStrict | tyrep == typeOf "" = remap pack- | tyrep == typeOf B.empty = remap F.decode- | tyrep == typeOf L.empty = remap strict | otherwise = modError "toJSON" $ "cannot convert map keyed by type " ++ show tyrep where tyrep = typeOf . head . Map.keys $ m@@ -140,8 +133,6 @@ | tyrep == typeOf DT.empty = remap id | tyrep == typeOf LT.empty = remap LT.toStrict | tyrep == typeOf "" = remap pack- | tyrep == typeOf B.empty = remap F.decode- | tyrep == typeOf L.empty = remap strict | otherwise = modError "toJSON" $ "cannot convert map keyed by type " ++ show tyrep where tyrep = typeOf . head . H.keys $ m@@ -214,8 +205,6 @@ `extR` (value :: F Text) `extR` (value :: F LT.Text) `extR` (value :: F String)- `extR` (value :: F B.ByteString)- `extR` (value :: F L.ByteString) `extR` (value :: F T.Value) `extR` (value :: F DotNetTime) `extR` (value :: F UTCTime)@@ -239,8 +228,6 @@ | tyrep == typeOf DT.empty = process id | tyrep == typeOf LT.empty = process LT.fromStrict | tyrep == typeOf "" = process DT.unpack- | tyrep == typeOf B.empty = process encodeUtf8- | tyrep == typeOf L.empty = process lazy | otherwise = myFail where process f = maybe myFail return . cast =<< parseWith f@@ -256,8 +243,6 @@ | tyrep == typeOf DT.empty = process id | tyrep == typeOf LT.empty = process LT.fromStrict | tyrep == typeOf "" = process DT.unpack- | tyrep == typeOf B.empty = process encodeUtf8- | tyrep == typeOf L.empty = process lazy | otherwise = myFail where process f = maybe myFail return . cast =<< parseWith f
Data/Aeson/Parser/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE CPP, BangPatterns, OverloadedStrings #-} -- | -- Module: Data.Aeson.Parser.Internal@@ -28,28 +28,55 @@ , eitherDecodeStrictWith ) where -import Blaze.ByteString.Builder (fromByteString, toByteString)+#if defined(USE_BLAZE_BUILDER)+import Blaze.ByteString.Builder (Builder, fromByteString, toByteString) import Blaze.ByteString.Builder.Char.Utf8 (fromChar) import Blaze.ByteString.Builder.Word (fromWord8)-import Control.Applicative as A+#else+#if MIN_VERSION_bytestring(0,10,2)+import Data.ByteString.Builder+#else+import Data.ByteString.Lazy.Builder+#endif+ (Builder, byteString, toLazyByteString, charUtf8, word8)+#endif++import Control.Applicative ((*>), (<$>), (<*), liftA2, pure) import Data.Aeson.Types (Result(..), Value(..))-import Data.Attoparsec.Char8 hiding (Result)+import Data.Attoparsec.Char8 (Parser, char, endOfInput, rational,+ skipSpace, string) import Data.Bits ((.|.), shiftL)-import Data.ByteString as B+import Data.ByteString (ByteString) import Data.Char (chr) import Data.Monoid (mappend, mempty)-import Data.Text as T+import Data.Text (Text) import Data.Text.Encoding (decodeUtf8')-import Data.Vector as Vector hiding ((++))+import Data.Vector as Vector (Vector, fromList) import Data.Word (Word8) import qualified Data.Attoparsec as A import qualified Data.Attoparsec.Lazy as L import qualified Data.Attoparsec.Zepto as Z-import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Unsafe as B import qualified Data.HashMap.Strict as H +#define BACKSLASH 92+#define CLOSE_CURLY 125+#define CLOSE_SQUARE 93+#define COMMA 44+#define DOUBLE_QUOTE 34+#define OPEN_CURLY 123+#define OPEN_SQUARE 91+#define C_0 48+#define C_9 57+#define C_A 65+#define C_F 70+#define C_a 97+#define C_f 102+#define C_n 110+#define C_t 116+ -- | Parse a top-level JSON value. This must be either an object or -- an array, per RFC 4627. --@@ -71,8 +98,8 @@ json_ :: Parser Value -> Parser Value -> Parser Value json_ obj ary = do- w <- skipSpace *> A.satisfy (\w -> w == 123 || w == 91)- if w == 123+ w <- skipSpace *> A.satisfy (\w -> w == OPEN_CURLY || w == OPEN_SQUARE)+ if w == OPEN_CURLY then obj else ary {-# INLINE json_ #-}@@ -92,12 +119,8 @@ objectValues :: Parser Text -> Parser Value -> Parser (H.HashMap Text Value) objectValues str val = do skipSpace- let pair = do- a <- str <* skipSpace- b <- char ':' *> skipSpace *> val- return (a,b)- vals <- ((pair <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char '}'- return (H.fromList vals)+ let pair = liftA2 (,) (str <* skipSpace) (char ':' *> skipSpace *> val)+ H.fromList <$> commaSeparated pair CLOSE_CURLY {-# INLINE objectValues #-} array_ :: Parser Value@@ -108,11 +131,25 @@ !vals <- arrayValues value' return (Array vals) +commaSeparated :: Parser a -> Word8 -> Parser [a]+commaSeparated item endByte = do+ w <- A.peekWord8'+ if w == endByte+ then A.anyWord8 >> return []+ else loop+ where+ loop = do+ v <- item <* skipSpace+ ch <- A.satisfy $ \w -> w == COMMA || w == endByte+ if ch == COMMA+ then skipSpace >> (v:) <$> loop+ else return [v]+{-# INLINE commaSeparated #-}+ arrayValues :: Parser Value -> Parser (Vector Value) arrayValues val = do skipSpace- vals <- ((val <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char ']'- return (Vector.fromList vals)+ Vector.fromList <$> commaSeparated val CLOSE_SQUARE {-# INLINE arrayValues #-} -- | Parse any JSON value. You should usually 'json' in preference to@@ -126,64 +163,57 @@ -- implementations in other languages conform to that same restriction -- to preserve interoperability and security. value :: Parser Value-value = most <|> (Number <$> number)- where- most = do- c <- satisfy (`B8.elem` "{[\"ftn")- case c of- '{' -> object_- '[' -> array_- '"' -> String <$> jstring_- 'f' -> string "alse" *> pure (Bool False)- 't' -> string "rue" *> pure (Bool True)- 'n' -> string "ull" *> pure Null- _ -> error "attoparsec panic! the impossible happened!"+value = do+ w <- A.peekWord8'+ case w of+ DOUBLE_QUOTE -> A.anyWord8 *> (String <$> jstring_)+ OPEN_CURLY -> A.anyWord8 *> object_+ OPEN_SQUARE -> A.anyWord8 *> array_+ C_f -> string "false" *> pure (Bool False)+ C_t -> string "true" *> pure (Bool True)+ C_n -> string "null" *> pure Null+ _ | w >= 48 && w <= 57 || w == 45+ -> Number <$> rational+ | otherwise -> fail "not a valid json value" -- | Strict version of 'value'. See also 'json''. value' :: Parser Value-value' = most <|> num- where- most = do- c <- satisfy (`B8.elem` "{[\"ftn")- case c of- '{' -> object_'- '[' -> array_'- '"' -> do- !s <- jstring_- return (String s)- 'f' -> string "alse" *> pure (Bool False)- 't' -> string "rue" *> pure (Bool True)- 'n' -> string "ull" *> pure Null- _ -> error "attoparsec panic! the impossible happened!"- num = do- !n <- number- return (Number n)--doubleQuote, backslash :: Word8-doubleQuote = 34-backslash = 92-{-# INLINE backslash #-}-{-# INLINE doubleQuote #-}+value' = do+ w <- A.peekWord8'+ case w of+ DOUBLE_QUOTE -> do+ !s <- A.anyWord8 *> jstring_+ return (String s)+ OPEN_CURLY -> A.anyWord8 *> object_'+ OPEN_SQUARE -> A.anyWord8 *> array_'+ C_f -> string "false" *> pure (Bool False)+ C_t -> string "true" *> pure (Bool True)+ C_n -> string "null" *> pure Null+ _ | w >= 48 && w <= 57 || w == 45+ -> do+ !n <- rational+ return (Number n)+ | otherwise -> fail "not a valid json value" -- | Parse a quoted JSON string. jstring :: Parser Text-jstring = A.word8 doubleQuote *> jstring_+jstring = A.word8 DOUBLE_QUOTE *> jstring_ -- | Parse a string without a leading quote. jstring_ :: Parser Text jstring_ = {-# SCC "jstring_" #-} do s <- A.scan False $ \s c -> if s then Just False- else if c == doubleQuote+ else if c == DOUBLE_QUOTE then Nothing- else Just (c == backslash)- _ <- A.word8 doubleQuote- s' <- if backslash `B.elem` s+ else Just (c == BACKSLASH)+ _ <- A.word8 DOUBLE_QUOTE+ s1 <- if BACKSLASH `B.elem` s then case Z.parse unescape s of Right r -> return r Left err -> fail err else return s - case decodeUtf8' s' of+ case decodeUtf8' s1 of Right r -> return r Left err -> fail $ show err @@ -192,7 +222,7 @@ unescape :: Z.Parser ByteString unescape = toByteString <$> go mempty where go acc = do- h <- Z.takeWhile (/=backslash)+ h <- Z.takeWhile (/=BACKSLASH) let rest = do start <- Z.take 2 let !slash = B.unsafeHead start@@ -200,37 +230,37 @@ escape = case B.findIndex (==t) "\"\\/ntbrfu" of Just i -> i _ -> 255- if slash /= backslash || escape == 255+ if slash /= BACKSLASH || escape == 255 then fail "invalid JSON escape sequence" else do- let cont m = go (acc `mappend` fromByteString h `mappend` m)+ let cont m = go (acc `mappend` byteString h `mappend` m) {-# INLINE cont #-} if t /= 117 -- 'u'- then cont (fromWord8 (B.unsafeIndex mapping escape))+ then cont (word8 (B.unsafeIndex mapping escape)) else do a <- hexQuad if a < 0xd800 || a > 0xdfff- then cont (fromChar (chr a))+ then cont (charUtf8 (chr a)) else do b <- Z.string "\\u" *> hexQuad if a <= 0xdbff && b >= 0xdc00 && b <= 0xdfff then let !c = ((a - 0xd800) `shiftL` 10) + (b - 0xdc00) + 0x10000- in cont (fromChar (chr c))+ in cont (charUtf8 (chr c)) else fail "invalid UTF-16 surrogates" done <- Z.atEnd if done- then return (acc `mappend` fromByteString h)+ then return (acc `mappend` byteString h) else rest mapping = "\"\\/\n\t\b\r\f" hexQuad :: Z.Parser Int hexQuad = do s <- Z.take 4- let hex n | w >= 48 && w <= 57 = w - 48- | w >= 97 && w <= 122 = w - 87- | w >= 65 && w <= 90 = w - 55- | otherwise = 255+ let hex n | w >= C_0 && w <= C_9 = w - C_0+ | w >= C_a && w <= C_f = w - 87+ | w >= C_A && w <= C_F = w - 55+ | otherwise = 255 where w = fromIntegral $ B.unsafeIndex s n a = hex 0; b = hex 1; c = hex 2; d = hex 3 if (a .|. b .|. c .|. d) /= 255@@ -249,11 +279,9 @@ decodeStrictWith :: Parser Value -> (Value -> Result a) -> B.ByteString -> Maybe a decodeStrictWith p to s =- case A.parse p s of- A.Done _ v -> case to v of- Success a -> Just a- _ -> Nothing- _ -> Nothing+ case either Error to (A.parseOnly p s) of+ Success a -> Just a+ Error _ -> Nothing {-# INLINE decodeStrictWith #-} eitherDecodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString@@ -269,12 +297,9 @@ eitherDecodeStrictWith :: Parser Value -> (Value -> Result a) -> B.ByteString -> Either String a eitherDecodeStrictWith p to s =- case A.parse p s of- A.Done _ v -> case to v of- Success a -> Right a- Error msg -> Left msg- A.Fail _ _ msg -> Left msg- A.Partial _ -> Left "incomplete input"+ case either Error to (A.parseOnly p s) of+ Success a -> Right a+ Error msg -> Left msg {-# INLINE eitherDecodeStrictWith #-} -- $lazy@@ -305,3 +330,22 @@ -- end-of-input. See also: 'json''. jsonEOF' :: Parser Value jsonEOF' = json' <* skipSpace <* endOfInput++#if defined(USE_BLAZE_BUILDER)+byteString :: ByteString -> Builder+byteString = fromByteString+{-# INLINE byteString #-}++charUtf8 :: Char -> Builder+charUtf8 = fromChar+{-# INLINE charUtf8 #-}++word8 :: Word8 -> Builder+word8 = fromWord8+{-# INLINE word8 #-}++#else+toByteString :: Builder -> ByteString+toByteString = L.toStrict . toLazyByteString+{-# INLINE toByteString #-}+#endif
Data/Aeson/Types.hs view
@@ -47,6 +47,7 @@ , withText , withArray , withNumber+ , withScientific , withBool -- * Constructors and accessors@@ -63,7 +64,7 @@ , defaultTaggedObject ) where -import Data.Aeson.Types.Class+import Data.Aeson.Types.Instances import Data.Aeson.Types.Internal #ifdef GENERICS
Data/Aeson/Types/Class.hs view
@@ -1,7 +1,4 @@-{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, FlexibleInstances,- GeneralizedNewtypeDeriving, IncoherentInstances, OverlappingInstances,- OverloadedStrings, UndecidableInstances, ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE CPP, FlexibleContexts #-} #ifdef GENERICS {-# LANGUAGE DefaultSignatures #-}@@ -9,7 +6,7 @@ -- | -- Module: Data.Aeson.Types.Class--- Copyright: (c) 2011, 2012 Bryan O'Sullivan+-- Copyright: (c) 2011-2013 Bryan O'Sullivan -- (c) 2011 MailRank, Inc. -- License: Apache -- Maintainer: Bryan O'Sullivan <bos@serpentine.com>@@ -31,61 +28,9 @@ , genericToJSON , genericParseJSON #endif- -- * Types- , DotNetTime(..)-- -- * Inspecting @'Value's@- , withObject- , withText- , withArray- , withNumber- , withBool-- -- * Functions- , fromJSON- , (.:)- , (.:?)- , (.!=)- , (.=)- , typeMismatch ) where -import Control.Applicative ((<$>), (<*>), (<|>), pure, empty)-import Data.Aeson.Functions import Data.Aeson.Types.Internal-import Data.Attoparsec.Char8 (Number(..))-import Data.Fixed-import Data.Hashable (Hashable(..))-import Data.Int (Int8, Int16, Int32, Int64)-import Data.Maybe (fromMaybe)-import Data.Monoid (Dual(..), First(..), Last(..), mappend)-import Data.Ratio (Ratio)-import Data.Text (Text, pack, unpack)-import Data.Text.Encoding (encodeUtf8)-import Data.Time (UTCTime, ZonedTime(..), TimeZone(..))-import Data.Time.Format (FormatTime, formatTime, parseTime)-import Data.Traversable (traverse)-import Data.Typeable (Typeable)-import Data.Vector (Vector)-import Data.Word (Word, Word8, Word16, Word32, Word64)-import Foreign.Storable (Storable)-import System.Locale (defaultTimeLocale, dateTimeFmt)-import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as LB-import qualified Data.HashMap.Strict as H-import qualified Data.HashSet as HashSet-import qualified Data.IntMap as IntMap-import qualified Data.IntSet as IntSet-import qualified Data.Map as M-import qualified Data.Set as Set-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import qualified Data.Vector as V-import qualified Data.Vector.Generic as VG-import qualified Data.Vector.Primitive as VP-import qualified Data.Vector.Storable as VS-import qualified Data.Vector.Unboxed as VU-import qualified Data.Vector.Mutable as VM ( unsafeNew, unsafeWrite ) #ifdef GENERICS import GHC.Generics@@ -245,650 +190,3 @@ default parseJSON :: (Generic a, GFromJSON (Rep a)) => Value -> Parser a parseJSON = genericParseJSON defaultOptions #endif--instance (ToJSON a) => ToJSON (Maybe a) where- toJSON (Just a) = toJSON a- toJSON Nothing = Null- {-# INLINE toJSON #-}--instance (FromJSON a) => FromJSON (Maybe a) where- parseJSON Null = pure Nothing- parseJSON a = Just <$> parseJSON a- {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b) => ToJSON (Either a b) where- toJSON (Left a) = object [left .= a]- toJSON (Right b) = object [right .= b]- {-# INLINE toJSON #-}--instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where- parseJSON (Object (H.toList -> [(key, value)]))- | key == left = Left <$> parseJSON value- | key == right = Right <$> parseJSON value- parseJSON _ = fail ""- {-# INLINE parseJSON #-}--left, right :: Text-left = "Left"-right = "Right"--instance ToJSON Bool where- toJSON = Bool- {-# INLINE toJSON #-}--instance FromJSON Bool where- parseJSON = withBool "Bool" pure- {-# INLINE parseJSON #-}--instance ToJSON () where- toJSON _ = emptyArray- {-# INLINE toJSON #-}--instance FromJSON () where- parseJSON = withArray "()" $ \v ->- if V.null v- then pure ()- else fail "Expected an empty array"- {-# INLINE parseJSON #-}--instance ToJSON [Char] where- toJSON = String . T.pack- {-# INLINE toJSON #-}--instance FromJSON [Char] where- parseJSON = withText "String" $ pure . T.unpack- {-# INLINE parseJSON #-}--instance ToJSON Char where- toJSON = String . T.singleton- {-# INLINE toJSON #-}--instance FromJSON Char where- parseJSON = withText "Char" $ \t ->- if T.compareLength t 1 == EQ- then pure $ T.head t- else fail "Expected a string of length 1"- {-# INLINE parseJSON #-}--instance ToJSON Double where- toJSON = Number . D- {-# INLINE toJSON #-}--instance FromJSON Double where- parseJSON (Number n) = case n of- D d -> pure d- I i -> pure (fromIntegral i)- parseJSON Null = pure (0/0)- parseJSON v = typeMismatch "Double" v- {-# INLINE parseJSON #-}--instance ToJSON Number where- toJSON = Number- {-# INLINE toJSON #-}--instance FromJSON Number where- parseJSON (Number n) = pure n- parseJSON Null = pure (D (0/0))- parseJSON v = typeMismatch "Number" v- {-# INLINE parseJSON #-}--instance ToJSON Float where- toJSON = Number . realToFrac- {-# INLINE toJSON #-}--instance FromJSON Float where- parseJSON (Number n) = pure $ case n of- D d -> realToFrac d- I i -> fromIntegral i- parseJSON Null = pure (0/0)- parseJSON v = typeMismatch "Float" v- {-# INLINE parseJSON #-}--instance ToJSON (Ratio Integer) where- toJSON = Number . fromRational- {-# INLINE toJSON #-}--instance FromJSON (Ratio Integer) where- parseJSON = withNumber "Ration Integer" $ \n ->- pure $ case n of- D d -> toRational d- I i -> fromIntegral i- {-# INLINE parseJSON #-}--instance HasResolution a => ToJSON (Fixed a) where- toJSON = Number . realToFrac- {-# INLINE toJSON #-}--instance HasResolution a => FromJSON (Fixed a) where- parseJSON (Number n) = pure $ case n of- D d -> realToFrac d- I i -> fromIntegral i- parseJSON v = typeMismatch "Fixed" v- {-# INLINE parseJSON #-}--instance ToJSON Int where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Int where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--parseIntegral :: Integral a => Value -> Parser a-parseIntegral = withNumber "Integral" $ pure . floor-{-# INLINE parseIntegral #-}--instance ToJSON Integer where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Integer where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Int8 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Int8 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Int16 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Int16 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Int32 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Int32 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Int64 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Int64 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Word where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Word where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Word8 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Word8 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Word16 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Word16 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Word32 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Word32 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Word64 where- toJSON = Number . fromIntegral- {-# INLINE toJSON #-}--instance FromJSON Word64 where- parseJSON = parseIntegral- {-# INLINE parseJSON #-}--instance ToJSON Text where- toJSON = String- {-# INLINE toJSON #-}--instance FromJSON Text where- parseJSON = withText "Text" pure- {-# INLINE parseJSON #-}--instance ToJSON LT.Text where- toJSON = String . LT.toStrict- {-# INLINE toJSON #-}--instance FromJSON LT.Text where- parseJSON = withText "Lazy Text" $ pure . LT.fromStrict- {-# INLINE parseJSON #-}--instance ToJSON B.ByteString where- toJSON = String . decode- {-# INLINE toJSON #-}--instance FromJSON B.ByteString where- parseJSON = withText "ByteString" $ pure . encodeUtf8- {-# INLINE parseJSON #-}--instance ToJSON LB.ByteString where- toJSON = toJSON . strict- {-# INLINE toJSON #-}--instance FromJSON LB.ByteString where- parseJSON = withText "Lazy ByteString" $ pure . lazy- {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON [a] where- toJSON = Array . V.fromList . map toJSON- {-# INLINE toJSON #-}--instance (FromJSON a) => FromJSON [a] where- parseJSON = withArray "[a]" $ mapM parseJSON . V.toList- {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (Vector a) where- toJSON = Array . V.map toJSON- {-# INLINE toJSON #-}--instance (FromJSON a) => FromJSON (Vector a) where- parseJSON = withArray "Vector a" $ V.mapM parseJSON- {-# INLINE parseJSON #-}--vectorToJSON :: (VG.Vector v a, ToJSON a) => v a -> Value-vectorToJSON = Array . V.map toJSON . V.convert-{-# INLINE vectorToJSON #-}--vectorParseJSON :: (FromJSON a, VG.Vector w a) => String -> Value -> Parser (w a)-vectorParseJSON s = withArray s $ fmap V.convert . V.mapM parseJSON-{-# INLINE vectorParseJSON #-}--instance (Storable a, ToJSON a) => ToJSON (VS.Vector a) where- toJSON = vectorToJSON--instance (Storable a, FromJSON a) => FromJSON (VS.Vector a) where- parseJSON = vectorParseJSON "Data.Vector.Storable.Vector a"--instance (VP.Prim a, ToJSON a) => ToJSON (VP.Vector a) where- toJSON = vectorToJSON--instance (VP.Prim a, FromJSON a) => FromJSON (VP.Vector a) where- parseJSON = vectorParseJSON "Data.Vector.Primitive.Vector a"--instance (VG.Vector VU.Vector a, ToJSON a) => ToJSON (VU.Vector a) where- toJSON = vectorToJSON--instance (VG.Vector VU.Vector a, FromJSON a) => FromJSON (VU.Vector a) where- parseJSON = vectorParseJSON "Data.Vector.Unboxed.Vector a"--instance (ToJSON a) => ToJSON (Set.Set a) where- toJSON = toJSON . Set.toList- {-# INLINE toJSON #-}--instance (Ord a, FromJSON a) => FromJSON (Set.Set a) where- parseJSON = fmap Set.fromList . parseJSON- {-# INLINE parseJSON #-}--instance (ToJSON a) => ToJSON (HashSet.HashSet a) where- toJSON = toJSON . HashSet.toList- {-# INLINE toJSON #-}--instance (Eq a, Hashable a, FromJSON a) => FromJSON (HashSet.HashSet a) where- parseJSON = fmap HashSet.fromList . parseJSON- {-# INLINE parseJSON #-}--instance ToJSON IntSet.IntSet where- toJSON = toJSON . IntSet.toList- {-# INLINE toJSON #-}--instance FromJSON IntSet.IntSet where- parseJSON = fmap IntSet.fromList . parseJSON- {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (IntMap.IntMap a) where- toJSON = toJSON . IntMap.toList- {-# INLINE toJSON #-}--instance FromJSON a => FromJSON (IntMap.IntMap a) where- parseJSON = fmap IntMap.fromList . parseJSON- {-# INLINE parseJSON #-}--instance (ToJSON v) => ToJSON (M.Map Text v) where- toJSON = Object . M.foldrWithKey (\k -> H.insert k . toJSON) H.empty- {-# INLINE toJSON #-}--instance (FromJSON v) => FromJSON (M.Map Text v) where- parseJSON = withObject "Map Text a" $- fmap (H.foldrWithKey M.insert M.empty) . traverse parseJSON--instance (ToJSON v) => ToJSON (M.Map LT.Text v) where- toJSON = Object . mapHashKeyVal LT.toStrict toJSON--instance (FromJSON v) => FromJSON (M.Map LT.Text v) where- parseJSON = fmap (hashMapKey LT.fromStrict) . parseJSON--instance (ToJSON v) => ToJSON (M.Map String v) where- toJSON = Object . mapHashKeyVal pack toJSON--instance (FromJSON v) => FromJSON (M.Map String v) where- parseJSON = fmap (hashMapKey unpack) . parseJSON--instance (ToJSON v) => ToJSON (M.Map B.ByteString v) where- toJSON = Object . mapHashKeyVal decode toJSON--instance (FromJSON v) => FromJSON (M.Map B.ByteString v) where- parseJSON = fmap (hashMapKey encodeUtf8) . parseJSON--instance (ToJSON v) => ToJSON (M.Map LB.ByteString v) where- toJSON = Object . mapHashKeyVal strict toJSON--instance (FromJSON v) => FromJSON (M.Map LB.ByteString v) where- parseJSON = fmap (hashMapKey lazy) . parseJSON--instance (ToJSON v) => ToJSON (H.HashMap Text v) where- toJSON = Object . H.map toJSON- {-# INLINE toJSON #-}--instance (FromJSON v) => FromJSON (H.HashMap Text v) where- parseJSON = withObject "HashMap Text a" $ traverse parseJSON--instance (ToJSON v) => ToJSON (H.HashMap LT.Text v) where- toJSON = Object . mapKeyVal LT.toStrict toJSON--instance (FromJSON v) => FromJSON (H.HashMap LT.Text v) where- parseJSON = fmap (mapKey LT.fromStrict) . parseJSON--instance (ToJSON v) => ToJSON (H.HashMap String v) where- toJSON = Object . mapKeyVal pack toJSON--instance (FromJSON v) => FromJSON (H.HashMap String v) where- parseJSON = fmap (mapKey unpack) . parseJSON--instance (ToJSON v) => ToJSON (H.HashMap B.ByteString v) where- toJSON = Object . mapKeyVal decode toJSON--instance (FromJSON v) => FromJSON (H.HashMap B.ByteString v) where- parseJSON = fmap (mapKey encodeUtf8) . parseJSON--instance (ToJSON v) => ToJSON (H.HashMap LB.ByteString v) where- toJSON = Object . mapKeyVal strict toJSON--instance (FromJSON v) => FromJSON (H.HashMap LB.ByteString v) where- parseJSON = fmap (mapKey lazy) . parseJSON--instance ToJSON Value where- toJSON a = a- {-# INLINE toJSON #-}--instance FromJSON Value where- parseJSON a = pure a- {-# INLINE parseJSON #-}---- | A newtype wrapper for 'UTCTime' that uses the same non-standard--- serialization format as Microsoft .NET, whose @System.DateTime@--- type is by default serialized to JSON as in the following example:------ > /Date(1302547608878)/------ The number represents milliseconds since the Unix epoch.-newtype DotNetTime = DotNetTime {- fromDotNetTime :: UTCTime- } deriving (Eq, Ord, Read, Show, Typeable, FormatTime)--instance ToJSON DotNetTime where- toJSON (DotNetTime t) =- String (pack (secs ++ msecs ++ ")/"))- where secs = formatTime defaultTimeLocale "/Date(%s" t- msecs = take 3 $ formatTime defaultTimeLocale "%q" t- {-# INLINE toJSON #-}--instance FromJSON DotNetTime where- parseJSON = withText "DotNetTime" $ \t ->- let (s,m) = T.splitAt (T.length t - 5) t- t' = T.concat [s,".",m]- in case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of- Just d -> pure (DotNetTime d)- _ -> fail "could not parse .NET time"- {-# INLINE parseJSON #-}--instance ToJSON ZonedTime where- toJSON t = String $ pack $ formatTime defaultTimeLocale format t- where- format = "%FT%T" ++ milliseconds ++ tzFormat- milliseconds = take 4 $ formatTime defaultTimeLocale "%Q" t- tzFormat- | 0 == timeZoneMinutes (zonedTimeZone t) = "Z"- | otherwise = "%z"--instance FromJSON ZonedTime where- parseJSON (String t) =- tryFormats alternateFormats- <|> fail "could not parse ECMA-262 ISO-8601 date"- where- tryFormat f =- case parseTime defaultTimeLocale f (unpack t) of- Just d -> pure d- Nothing -> empty- tryFormats = foldr1 (<|>) . map tryFormat- alternateFormats =- dateTimeFmt defaultTimeLocale :- distributeList ["%Y", "%Y-%m", "%F"]- ["T%R", "T%T", "T%T%Q", "T%T%QZ", "T%T%Q%z"]-- distributeList xs ys =- foldr (\x acc -> acc ++ distribute x ys) [] xs- distribute x = map (mappend x)-- parseJSON v = typeMismatch "ZonedTime" v--instance ToJSON UTCTime where- toJSON t = String (pack (take 23 str ++ "Z"))- where str = formatTime defaultTimeLocale "%FT%T%Q" t- {-# INLINE toJSON #-}--instance FromJSON UTCTime where- parseJSON = withText "UTCTime" $ \t ->- case parseTime defaultTimeLocale "%FT%T%QZ" (unpack t) of- Just d -> pure d- _ -> fail "could not parse ISO-8601 date"- {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b) => ToJSON (a,b) where- toJSON (a,b) = Array $ V.create $ do- mv <- VM.unsafeNew 2- VM.unsafeWrite mv 0 (toJSON a)- VM.unsafeWrite mv 1 (toJSON b)- return mv- {-# INLINE toJSON #-}--instance (FromJSON a, FromJSON b) => FromJSON (a,b) where- parseJSON = withArray "(a,b)" $ \ab ->- let n = V.length ab- in if n == 2- then (,) <$> parseJSON (V.unsafeIndex ab 0)- <*> parseJSON (V.unsafeIndex ab 1)- else fail $ "cannot unpack array of length " ++- show n ++ " into a pair"- {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON (a,b,c) where- toJSON (a,b,c) = Array $ V.create $ do- mv <- VM.unsafeNew 3- VM.unsafeWrite mv 0 (toJSON a)- VM.unsafeWrite mv 1 (toJSON b)- VM.unsafeWrite mv 2 (toJSON c)- return mv- {-# INLINE toJSON #-}--instance (FromJSON a, FromJSON b, FromJSON c) => FromJSON (a,b,c) where- parseJSON = withArray "(a,b,c)" $ \abc ->- let n = V.length abc- in if n == 3- then (,,) <$> parseJSON (V.unsafeIndex abc 0)- <*> parseJSON (V.unsafeIndex abc 1)- <*> parseJSON (V.unsafeIndex abc 2)- else fail $ "cannot unpack array of length " ++- show n ++ " into a 3-tuple"- {-# INLINE parseJSON #-}--instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON (a,b,c,d) where- toJSON (a,b,c,d) = Array $ V.create $ do- mv <- VM.unsafeNew 4- VM.unsafeWrite mv 0 (toJSON a)- VM.unsafeWrite mv 1 (toJSON b)- VM.unsafeWrite mv 2 (toJSON c)- VM.unsafeWrite mv 3 (toJSON d)- return mv- {-# INLINE toJSON #-}--instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSON (a,b,c,d) where- parseJSON = withArray "(a,b,c,d)" $ \abcd ->- let n = V.length abcd- in if n == 4- then (,,,) <$> parseJSON (V.unsafeIndex abcd 0)- <*> parseJSON (V.unsafeIndex abcd 1)- <*> parseJSON (V.unsafeIndex abcd 2)- <*> parseJSON (V.unsafeIndex abcd 3)- else fail $ "cannot unpack array of length " ++- show n ++ " into a 4-tuple"- {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (Dual a) where- toJSON = toJSON . getDual- {-# INLINE toJSON #-}--instance FromJSON a => FromJSON (Dual a) where- parseJSON = fmap Dual . parseJSON- {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (First a) where- toJSON = toJSON . getFirst- {-# INLINE toJSON #-}--instance FromJSON a => FromJSON (First a) where- parseJSON = fmap First . parseJSON- {-# INLINE parseJSON #-}--instance ToJSON a => ToJSON (Last a) where- toJSON = toJSON . getLast- {-# INLINE toJSON #-}--instance FromJSON a => FromJSON (Last a) where- parseJSON = fmap Last . parseJSON- {-# INLINE parseJSON #-}---- | @withObject expected f value@ applies @f@ to the 'Object' when @value@ is an @Object@--- and fails using @'typeMismatch' expected@ otherwise.-withObject :: String -> (Object -> Parser a) -> Value -> Parser a-withObject _ f (Object obj) = f obj-withObject expected _ v = typeMismatch expected v-{-# INLINE withObject #-}---- | @withObject expected f value@ applies @f@ to the 'Text' when @value@ is a @String@--- and fails using @'typeMismatch' expected@ otherwise.-withText :: String -> (Text -> Parser a) -> Value -> Parser a-withText _ f (String txt) = f txt-withText expected _ v = typeMismatch expected v-{-# INLINE withText #-}---- | @withObject expected f value@ applies @f@ to the 'Array' when @value@ is an @Array@--- and fails using @'typeMismatch' expected@ otherwise.-withArray :: String -> (Array -> Parser a) -> Value -> Parser a-withArray _ f (Array arr) = f arr-withArray expected _ v = typeMismatch expected v-{-# INLINE withArray #-}---- | @withObject expected f value@ applies @f@ to the 'Number' when @value@ is a @Number@--- and fails using @'typeMismatch' expected@ otherwise.-withNumber :: String -> (Number -> Parser a) -> Value -> Parser a-withNumber _ f (Number num) = f num-withNumber expected _ v = typeMismatch expected v-{-# INLINE withNumber #-}---- | @withObject expected f value@ applies @f@ to the 'Bool' when @value@ is a @Bool@--- and fails using @'typeMismatch' expected@ otherwise.-withBool :: String -> (Bool -> Parser a) -> Value -> Parser a-withBool _ f (Bool arr) = f arr-withBool expected _ v = typeMismatch expected v-{-# INLINE withBool #-}---- | Construct a 'Pair' from a key and a value.-(.=) :: ToJSON a => Text -> a -> Pair-name .= value = (name, toJSON value)-{-# INLINE (.=) #-}---- | Convert a value from JSON, failing if the types do not match.-fromJSON :: (FromJSON a) => Value -> Result a-fromJSON = parse parseJSON-{-# INLINE fromJSON #-}---- | Retrieve the value associated with the given key of an 'Object'.--- The result is 'empty' if the key is not present or the value cannot--- be converted to the desired type.------ This accessor is appropriate if the key and value /must/ be present--- in an object for it to be valid. If the key and value are--- optional, use '(.:?)' instead.-(.:) :: (FromJSON a) => Object -> Text -> Parser a-obj .: key = case H.lookup key obj of- Nothing -> fail $ "key " ++ show key ++ " not present"- Just v -> parseJSON v-{-# INLINE (.:) #-}---- | Retrieve the value associated with the given key of an 'Object'.--- The result is 'Nothing' if the key is not present, or 'empty' if--- the value cannot be converted to the desired type.------ This accessor is most useful if the key and value can be absent--- from an object without affecting its validity. If the key and--- value are mandatory, use '(.:)' instead.-(.:?) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)-obj .:? key = case H.lookup key obj of- Nothing -> pure Nothing- Just v -> parseJSON v-{-# INLINE (.:?) #-}---- | Helper for use in combination with '.:?' to provide default--- values for optional JSON object fields.------ This combinator is most useful if the key and value can be absent--- from an object without affecting its validity and we know a default--- value to assign in that case. If the key and value are mandatory,--- use '(.:)' instead.------ Example usage:------ @ v1 <- o '.:?' \"opt_field_with_dfl\" .!= \"default_val\"--- v2 <- o '.:' \"mandatory_field\"--- v3 <- o '.:?' \"opt_field2\"--- @-(.!=) :: Parser (Maybe a) -> a -> Parser a-pmval .!= val = fromMaybe val <$> pmval-{-# INLINE (.!=) #-}---- | Fail parsing due to a type mismatch, with a descriptive message.-typeMismatch :: String -- ^ The name of the type you are trying to parse.- -> Value -- ^ The actual value encountered.- -> Parser a-typeMismatch expected actual =- fail $ "when expecting a " ++ expected ++ ", encountered " ++ name ++- " instead"- where- name = case actual of- Object _ -> "Object"- Array _ -> "Array"- String _ -> "String"- Number _ -> "Number"- Bool _ -> "Boolean"- Null -> "Null"
Data/Aeson/Types/Generic.hs view
@@ -22,7 +22,7 @@ import Control.Applicative ((<*>), (<$>), (<|>), pure) import Control.Monad ((<=<)) import Control.Monad.ST (ST)-import Data.Aeson.Types.Class+import Data.Aeson.Types.Instances import Data.Aeson.Types.Internal import Data.Bits import Data.DList (DList, toList, empty)
+ Data/Aeson/Types/Instances.hs view
@@ -0,0 +1,795 @@+{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts, FlexibleInstances,+ GeneralizedNewtypeDeriving, IncoherentInstances, OverlappingInstances,+ OverloadedStrings, UndecidableInstances, ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++#ifdef GENERICS+{-# LANGUAGE DefaultSignatures #-}+#endif++-- |+-- Module: Data.Aeson.Types.Instances+-- Copyright: (c) 2011-2013 Bryan O'Sullivan+-- (c) 2011 MailRank, Inc.+-- License: Apache+-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>+-- Stability: experimental+-- Portability: portable+--+-- Types for working with JSON data.++module Data.Aeson.Types.Instances+ (+ -- * Type classes+ -- ** Core JSON classes+ FromJSON(..)+ , ToJSON(..)+#ifdef GENERICS+ -- ** Generic JSON classes+ , GFromJSON(..)+ , GToJSON(..)+ , genericToJSON+ , genericParseJSON+#endif+ -- * Types+ , DotNetTime(..)++ -- * Inspecting @'Value's@+ , withObject+ , withText+ , withArray+ , withNumber+ , withScientific+ , withBool++ -- * Functions+ , fromJSON+ , (.:)+ , (.:?)+ , (.!=)+ , (.=)+ , typeMismatch+ ) where++import Control.Applicative ((<$>), (<*>), (<|>), pure, empty)+import Data.Aeson.Functions+import Data.Aeson.Types.Class+import Data.Aeson.Types.Internal+import Data.Scientific (Scientific)+import qualified Data.Scientific as Scientific (coefficient, base10Exponent, fromFloatDigits)+import Data.Attoparsec.Number (Number(..))+import Data.Fixed+import Data.Hashable (Hashable(..))+import Data.Int (Int8, Int16, Int32, Int64)+import Data.Maybe (fromMaybe)+import Data.Monoid (Dual(..), First(..), Last(..), mappend)+import Data.Ratio (Ratio, (%), numerator, denominator)+import Data.Text (Text, pack, unpack)+import Data.Time (UTCTime, ZonedTime(..), TimeZone(..))+import Data.Time.Format (FormatTime, formatTime, parseTime)+import Data.Traversable (traverse)+import Data.Vector (Vector)+import Data.Word (Word, Word8, Word16, Word32, Word64)+import Foreign.Storable (Storable)+import System.Locale (defaultTimeLocale, dateTimeFmt)+import qualified Data.HashMap.Strict as H+import qualified Data.HashSet as HashSet+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.Map as M+import qualified Data.Set as Set+import qualified Data.Tree as Tree+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Primitive as VP+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Unboxed as VU+import qualified Data.Vector.Mutable as VM ( unsafeNew, unsafeWrite )++instance (ToJSON a) => ToJSON (Maybe a) where+ toJSON (Just a) = toJSON a+ toJSON Nothing = Null+ {-# INLINE toJSON #-}++instance (FromJSON a) => FromJSON (Maybe a) where+ parseJSON Null = pure Nothing+ parseJSON a = Just <$> parseJSON a+ {-# INLINE parseJSON #-}++instance (ToJSON a, ToJSON b) => ToJSON (Either a b) where+ toJSON (Left a) = object [left .= a]+ toJSON (Right b) = object [right .= b]+ {-# INLINE toJSON #-}++instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where+ parseJSON (Object (H.toList -> [(key, value)]))+ | key == left = Left <$> parseJSON value+ | key == right = Right <$> parseJSON value+ parseJSON _ = fail ""+ {-# INLINE parseJSON #-}++left, right :: Text+left = "Left"+right = "Right"++instance ToJSON Bool where+ toJSON = Bool+ {-# INLINE toJSON #-}++instance FromJSON Bool where+ parseJSON = withBool "Bool" pure+ {-# INLINE parseJSON #-}++instance ToJSON () where+ toJSON _ = emptyArray+ {-# INLINE toJSON #-}++instance FromJSON () where+ parseJSON = withArray "()" $ \v ->+ if V.null v+ then pure ()+ else fail "Expected an empty array"+ {-# INLINE parseJSON #-}++instance ToJSON [Char] where+ toJSON = String . T.pack+ {-# INLINE toJSON #-}++instance FromJSON [Char] where+ parseJSON = withText "String" $ pure . T.unpack+ {-# INLINE parseJSON #-}++instance ToJSON Char where+ toJSON = String . T.singleton+ {-# INLINE toJSON #-}++instance FromJSON Char where+ parseJSON = withText "Char" $ \t ->+ if T.compareLength t 1 == EQ+ then pure $ T.head t+ else fail "Expected a string of length 1"+ {-# INLINE parseJSON #-}++instance ToJSON Scientific where+ toJSON = Number+ {-# INLINE toJSON #-}++instance FromJSON Scientific where+ parseJSON = withScientific "Scientific" pure+ {-# INLINE parseJSON #-}++instance ToJSON Double where+ toJSON = realFloatToJSON+ {-# INLINE toJSON #-}++realFloatToJSON :: RealFloat a => a -> Value+realFloatToJSON d+ | isNaN d || isInfinite d = Null+ | otherwise = Number $ Scientific.fromFloatDigits d+{-# INLINE realFloatToJSON #-}++instance FromJSON Double where+ parseJSON (Number s) = pure $ realToFrac s+ parseJSON Null = pure (0/0)+ parseJSON v = typeMismatch "Double" v+ {-# INLINE parseJSON #-}++instance ToJSON Number where+ toJSON (D d) = toJSON d+ toJSON (I i) = toJSON i+ {-# INLINE toJSON #-}++instance FromJSON Number where+ parseJSON (Number s) = pure $ scientificToNumber s+ parseJSON Null = pure (D (0/0))+ parseJSON v = typeMismatch "Number" v+ {-# INLINE parseJSON #-}++instance ToJSON Float where+ toJSON = realFloatToJSON+ {-# INLINE toJSON #-}++instance FromJSON Float where+ parseJSON (Number s) = pure $ realToFrac s+ parseJSON Null = pure (0/0)+ parseJSON v = typeMismatch "Float" v+ {-# INLINE parseJSON #-}++instance ToJSON (Ratio Integer) where+ toJSON r = object [ "numerator" .= numerator r+ , "denominator" .= denominator r+ ]+ {-# INLINE toJSON #-}++instance FromJSON (Ratio Integer) where+ parseJSON = withObject "Rational" $ \obj ->+ (%) <$> obj .: "numerator"+ <*> obj .: "denominator"+ {-# INLINE parseJSON #-}++instance HasResolution a => ToJSON (Fixed a) where+ toJSON = Number . realToFrac+ {-# INLINE toJSON #-}++instance HasResolution a => FromJSON (Fixed a) where+ parseJSON = withScientific "Fixed" $ pure . realToFrac+ {-# INLINE parseJSON #-}++instance ToJSON Int where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Int where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++parseIntegral :: Integral a => Value -> Parser a+parseIntegral = withScientific "Integral" $ pure . floor+{-# INLINE parseIntegral #-}++instance ToJSON Integer where+ toJSON = Number . fromInteger+ {-# INLINE toJSON #-}++instance FromJSON Integer where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Int8 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Int8 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Int16 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Int16 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Int32 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Int32 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Int64 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Int64 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Word where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Word where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Word8 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Word8 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Word16 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Word16 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Word32 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Word32 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Word64 where+ toJSON = Number . fromIntegral+ {-# INLINE toJSON #-}++instance FromJSON Word64 where+ parseJSON = parseIntegral+ {-# INLINE parseJSON #-}++instance ToJSON Text where+ toJSON = String+ {-# INLINE toJSON #-}++instance FromJSON Text where+ parseJSON = withText "Text" pure+ {-# INLINE parseJSON #-}++instance ToJSON LT.Text where+ toJSON = String . LT.toStrict+ {-# INLINE toJSON #-}++instance FromJSON LT.Text where+ parseJSON = withText "Lazy Text" $ pure . LT.fromStrict+ {-# INLINE parseJSON #-}++instance (ToJSON a) => ToJSON [a] where+ toJSON = Array . V.fromList . map toJSON+ {-# INLINE toJSON #-}++instance (FromJSON a) => FromJSON [a] where+ parseJSON = withArray "[a]" $ mapM parseJSON . V.toList+ {-# INLINE parseJSON #-}++instance (ToJSON a) => ToJSON (Vector a) where+ toJSON = Array . V.map toJSON+ {-# INLINE toJSON #-}++instance (FromJSON a) => FromJSON (Vector a) where+ parseJSON = withArray "Vector a" $ V.mapM parseJSON+ {-# INLINE parseJSON #-}++vectorToJSON :: (VG.Vector v a, ToJSON a) => v a -> Value+vectorToJSON = Array . V.map toJSON . V.convert+{-# INLINE vectorToJSON #-}++vectorParseJSON :: (FromJSON a, VG.Vector w a) => String -> Value -> Parser (w a)+vectorParseJSON s = withArray s $ fmap V.convert . V.mapM parseJSON+{-# INLINE vectorParseJSON #-}++instance (Storable a, ToJSON a) => ToJSON (VS.Vector a) where+ toJSON = vectorToJSON++instance (Storable a, FromJSON a) => FromJSON (VS.Vector a) where+ parseJSON = vectorParseJSON "Data.Vector.Storable.Vector a"++instance (VP.Prim a, ToJSON a) => ToJSON (VP.Vector a) where+ toJSON = vectorToJSON++instance (VP.Prim a, FromJSON a) => FromJSON (VP.Vector a) where+ parseJSON = vectorParseJSON "Data.Vector.Primitive.Vector a"++instance (VG.Vector VU.Vector a, ToJSON a) => ToJSON (VU.Vector a) where+ toJSON = vectorToJSON++instance (VG.Vector VU.Vector a, FromJSON a) => FromJSON (VU.Vector a) where+ parseJSON = vectorParseJSON "Data.Vector.Unboxed.Vector a"++instance (ToJSON a) => ToJSON (Set.Set a) where+ toJSON = toJSON . Set.toList+ {-# INLINE toJSON #-}++instance (Ord a, FromJSON a) => FromJSON (Set.Set a) where+ parseJSON = fmap Set.fromList . parseJSON+ {-# INLINE parseJSON #-}++instance (ToJSON a) => ToJSON (HashSet.HashSet a) where+ toJSON = toJSON . HashSet.toList+ {-# INLINE toJSON #-}++instance (Eq a, Hashable a, FromJSON a) => FromJSON (HashSet.HashSet a) where+ parseJSON = fmap HashSet.fromList . parseJSON+ {-# INLINE parseJSON #-}++instance ToJSON IntSet.IntSet where+ toJSON = toJSON . IntSet.toList+ {-# INLINE toJSON #-}++instance FromJSON IntSet.IntSet where+ parseJSON = fmap IntSet.fromList . parseJSON+ {-# INLINE parseJSON #-}++instance ToJSON a => ToJSON (IntMap.IntMap a) where+ toJSON = toJSON . IntMap.toList+ {-# INLINE toJSON #-}++instance FromJSON a => FromJSON (IntMap.IntMap a) where+ parseJSON = fmap IntMap.fromList . parseJSON+ {-# INLINE parseJSON #-}++instance (ToJSON v) => ToJSON (M.Map Text v) where+ toJSON = Object . M.foldrWithKey (\k -> H.insert k . toJSON) H.empty+ {-# INLINE toJSON #-}++instance (FromJSON v) => FromJSON (M.Map Text v) where+ parseJSON = withObject "Map Text a" $+ fmap (H.foldrWithKey M.insert M.empty) . traverse parseJSON++instance (ToJSON v) => ToJSON (M.Map LT.Text v) where+ toJSON = Object . mapHashKeyVal LT.toStrict toJSON++instance (FromJSON v) => FromJSON (M.Map LT.Text v) where+ parseJSON = fmap (hashMapKey LT.fromStrict) . parseJSON++instance (ToJSON v) => ToJSON (M.Map String v) where+ toJSON = Object . mapHashKeyVal pack toJSON++instance (FromJSON v) => FromJSON (M.Map String v) where+ parseJSON = fmap (hashMapKey unpack) . parseJSON++instance (ToJSON v) => ToJSON (H.HashMap Text v) where+ toJSON = Object . H.map toJSON+ {-# INLINE toJSON #-}++instance (FromJSON v) => FromJSON (H.HashMap Text v) where+ parseJSON = withObject "HashMap Text a" $ traverse parseJSON++instance (ToJSON v) => ToJSON (H.HashMap LT.Text v) where+ toJSON = Object . mapKeyVal LT.toStrict toJSON++instance (FromJSON v) => FromJSON (H.HashMap LT.Text v) where+ parseJSON = fmap (mapKey LT.fromStrict) . parseJSON++instance (ToJSON v) => ToJSON (H.HashMap String v) where+ toJSON = Object . mapKeyVal pack toJSON++instance (FromJSON v) => FromJSON (H.HashMap String v) where+ parseJSON = fmap (mapKey unpack) . parseJSON++instance (ToJSON v) => ToJSON (Tree.Tree v) where+ toJSON (Tree.Node root branches) = toJSON (root,branches)++instance (FromJSON v) => FromJSON (Tree.Tree v) where+ parseJSON j = uncurry Tree.Node <$> parseJSON j++instance ToJSON Value where+ toJSON a = a+ {-# INLINE toJSON #-}++instance FromJSON Value where+ parseJSON a = pure a+ {-# INLINE parseJSON #-}++instance ToJSON DotNetTime where+ toJSON (DotNetTime t) =+ String (pack (secs ++ formatMillis t ++ ")/"))+ where secs = formatTime defaultTimeLocale "/Date(%s" t+ {-# INLINE toJSON #-}++instance FromJSON DotNetTime where+ parseJSON = withText "DotNetTime" $ \t ->+ let (s,m) = T.splitAt (T.length t - 5) t+ t' = T.concat [s,".",m]+ in case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of+ Just d -> pure (DotNetTime d)+ _ -> fail "could not parse .NET time"+ {-# INLINE parseJSON #-}++instance ToJSON ZonedTime where+ toJSON t = String $ pack $ formatTime defaultTimeLocale format t+ where+ format = "%FT%T." ++ formatMillis t ++ tzFormat+ tzFormat+ | 0 == timeZoneMinutes (zonedTimeZone t) = "Z"+ | otherwise = "%z"++formatMillis :: (FormatTime t) => t -> String+formatMillis t = take 3 . formatTime defaultTimeLocale "%q" $ t++instance FromJSON ZonedTime where+ parseJSON (String t) =+ tryFormats alternateFormats+ <|> fail "could not parse ECMA-262 ISO-8601 date"+ where+ tryFormat f =+ case parseTime defaultTimeLocale f (unpack t) of+ Just d -> pure d+ Nothing -> empty+ tryFormats = foldr1 (<|>) . map tryFormat+ alternateFormats =+ dateTimeFmt defaultTimeLocale :+ distributeList ["%Y", "%Y-%m", "%F"]+ ["T%R", "T%T", "T%T%Q", "T%T%QZ", "T%T%Q%z"]++ distributeList xs ys =+ foldr (\x acc -> acc ++ distribute x ys) [] xs+ distribute x = map (mappend x)++ parseJSON v = typeMismatch "ZonedTime" v++instance ToJSON UTCTime where+ toJSON t = String (pack (take 23 str ++ "Z"))+ where str = formatTime defaultTimeLocale "%FT%T.%q" t+ {-# INLINE toJSON #-}++instance FromJSON UTCTime where+ parseJSON = withText "UTCTime" $ \t ->+ case parseTime defaultTimeLocale "%FT%T%QZ" (unpack t) of+ Just d -> pure d+ _ -> fail "could not parse ISO-8601 date"+ {-# INLINE parseJSON #-}++instance (ToJSON a, ToJSON b) => ToJSON (a,b) where+ toJSON (a,b) = Array $ V.create $ do+ mv <- VM.unsafeNew 2+ VM.unsafeWrite mv 0 (toJSON a)+ VM.unsafeWrite mv 1 (toJSON b)+ return mv+ {-# INLINE toJSON #-}++instance (FromJSON a, FromJSON b) => FromJSON (a,b) where+ parseJSON = withArray "(a,b)" $ \ab ->+ let n = V.length ab+ in if n == 2+ then (,) <$> parseJSON (V.unsafeIndex ab 0)+ <*> parseJSON (V.unsafeIndex ab 1)+ else fail $ "cannot unpack array of length " +++ show n ++ " into a pair"+ {-# INLINE parseJSON #-}++instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON (a,b,c) where+ toJSON (a,b,c) = Array $ V.create $ do+ mv <- VM.unsafeNew 3+ VM.unsafeWrite mv 0 (toJSON a)+ VM.unsafeWrite mv 1 (toJSON b)+ VM.unsafeWrite mv 2 (toJSON c)+ return mv+ {-# INLINE toJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c) => FromJSON (a,b,c) where+ parseJSON = withArray "(a,b,c)" $ \abc ->+ let n = V.length abc+ in if n == 3+ then (,,) <$> parseJSON (V.unsafeIndex abc 0)+ <*> parseJSON (V.unsafeIndex abc 1)+ <*> parseJSON (V.unsafeIndex abc 2)+ else fail $ "cannot unpack array of length " +++ show n ++ " into a 3-tuple"+ {-# INLINE parseJSON #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON (a,b,c,d) where+ toJSON (a,b,c,d) = Array $ V.create $ do+ mv <- VM.unsafeNew 4+ VM.unsafeWrite mv 0 (toJSON a)+ VM.unsafeWrite mv 1 (toJSON b)+ VM.unsafeWrite mv 2 (toJSON c)+ VM.unsafeWrite mv 3 (toJSON d)+ return mv+ {-# INLINE toJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSON (a,b,c,d) where+ parseJSON = withArray "(a,b,c,d)" $ \abcd ->+ let n = V.length abcd+ in if n == 4+ then (,,,) <$> parseJSON (V.unsafeIndex abcd 0)+ <*> parseJSON (V.unsafeIndex abcd 1)+ <*> parseJSON (V.unsafeIndex abcd 2)+ <*> parseJSON (V.unsafeIndex abcd 3)+ else fail $ "cannot unpack array of length " +++ show n ++ " into a 4-tuple"+ {-# INLINE parseJSON #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON (a,b,c,d,e) where+ toJSON (a,b,c,d,e) = Array $ V.create $ do+ mv <- VM.unsafeNew 5+ VM.unsafeWrite mv 0 (toJSON a)+ VM.unsafeWrite mv 1 (toJSON b)+ VM.unsafeWrite mv 2 (toJSON c)+ VM.unsafeWrite mv 3 (toJSON d)+ VM.unsafeWrite mv 4 (toJSON e)+ return mv+ {-# INLINE toJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e) => FromJSON (a,b,c,d,e) where+ parseJSON = withArray "(a,b,c,d,e)" $ \abcde ->+ let n = V.length abcde+ in if n == 5+ then (,,,,) <$> parseJSON (V.unsafeIndex abcde 0)+ <*> parseJSON (V.unsafeIndex abcde 1)+ <*> parseJSON (V.unsafeIndex abcde 2)+ <*> parseJSON (V.unsafeIndex abcde 3)+ <*> parseJSON (V.unsafeIndex abcde 4)+ else fail $ "cannot unpack array of length " +++ show n ++ " into a 5-tuple"+ {-# INLINE parseJSON #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON (a,b,c,d,e,f) where+ toJSON (a,b,c,d,e,f) = Array $ V.create $ do+ mv <- VM.unsafeNew 6+ VM.unsafeWrite mv 0 (toJSON a)+ VM.unsafeWrite mv 1 (toJSON b)+ VM.unsafeWrite mv 2 (toJSON c)+ VM.unsafeWrite mv 3 (toJSON d)+ VM.unsafeWrite mv 4 (toJSON e)+ VM.unsafeWrite mv 5 (toJSON f)+ return mv+ {-# INLINE toJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f) => FromJSON (a,b,c,d,e,f) where+ parseJSON = withArray "(a,b,c,d,e,f)" $ \abcdef ->+ let n = V.length abcdef+ in if n == 6+ then (,,,,,) <$> parseJSON (V.unsafeIndex abcdef 0)+ <*> parseJSON (V.unsafeIndex abcdef 1)+ <*> parseJSON (V.unsafeIndex abcdef 2)+ <*> parseJSON (V.unsafeIndex abcdef 3)+ <*> parseJSON (V.unsafeIndex abcdef 4)+ <*> parseJSON (V.unsafeIndex abcdef 5)+ else fail $ "cannot unpack array of length " +++ show n ++ " into a 6-tuple"+ {-# INLINE parseJSON #-}++instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g) => ToJSON (a,b,c,d,e,f,g) where+ toJSON (a,b,c,d,e,f,g) = Array $ V.create $ do+ mv <- VM.unsafeNew 7+ VM.unsafeWrite mv 0 (toJSON a)+ VM.unsafeWrite mv 1 (toJSON b)+ VM.unsafeWrite mv 2 (toJSON c)+ VM.unsafeWrite mv 3 (toJSON d)+ VM.unsafeWrite mv 4 (toJSON e)+ VM.unsafeWrite mv 5 (toJSON f)+ VM.unsafeWrite mv 6 (toJSON g)+ return mv+ {-# INLINE toJSON #-}++instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g) => FromJSON (a,b,c,d,e,f,g) where+ parseJSON = withArray "(a,b,c,d,e,f,g)" $ \abcdefg ->+ let n = V.length abcdefg+ in if n == 7+ then (,,,,,,) <$> parseJSON (V.unsafeIndex abcdefg 0)+ <*> parseJSON (V.unsafeIndex abcdefg 1)+ <*> parseJSON (V.unsafeIndex abcdefg 2)+ <*> parseJSON (V.unsafeIndex abcdefg 3)+ <*> parseJSON (V.unsafeIndex abcdefg 4)+ <*> parseJSON (V.unsafeIndex abcdefg 5)+ <*> parseJSON (V.unsafeIndex abcdefg 6)+ else fail $ "cannot unpack array of length " +++ show n ++ " into a 7-tuple"+ {-# INLINE parseJSON #-}++instance ToJSON a => ToJSON (Dual a) where+ toJSON = toJSON . getDual+ {-# INLINE toJSON #-}++instance FromJSON a => FromJSON (Dual a) where+ parseJSON = fmap Dual . parseJSON+ {-# INLINE parseJSON #-}++instance ToJSON a => ToJSON (First a) where+ toJSON = toJSON . getFirst+ {-# INLINE toJSON #-}++instance FromJSON a => FromJSON (First a) where+ parseJSON = fmap First . parseJSON+ {-# INLINE parseJSON #-}++instance ToJSON a => ToJSON (Last a) where+ toJSON = toJSON . getLast+ {-# INLINE toJSON #-}++instance FromJSON a => FromJSON (Last a) where+ parseJSON = fmap Last . parseJSON+ {-# INLINE parseJSON #-}++-- | @withObject expected f value@ applies @f@ to the 'Object' when @value@ is an @Object@+-- and fails using @'typeMismatch' expected@ otherwise.+withObject :: String -> (Object -> Parser a) -> Value -> Parser a+withObject _ f (Object obj) = f obj+withObject expected _ v = typeMismatch expected v+{-# INLINE withObject #-}++-- | @withText expected f value@ applies @f@ to the 'Text' when @value@ is a @String@+-- and fails using @'typeMismatch' expected@ otherwise.+withText :: String -> (Text -> Parser a) -> Value -> Parser a+withText _ f (String txt) = f txt+withText expected _ v = typeMismatch expected v+{-# INLINE withText #-}++-- | @withArray expected f value@ applies @f@ to the 'Array' when @value@ is an @Array@+-- and fails using @'typeMismatch' expected@ otherwise.+withArray :: String -> (Array -> Parser a) -> Value -> Parser a+withArray _ f (Array arr) = f arr+withArray expected _ v = typeMismatch expected v+{-# INLINE withArray #-}++-- | @withNumber expected f value@ applies @f@ to the 'Number' when @value@ is a 'Number'.+-- and fails using @'typeMismatch' expected@ otherwise.+withNumber :: String -> (Number -> Parser a) -> Value -> Parser a+withNumber expected f = withScientific expected (f . scientificToNumber)+{-# INLINE withNumber #-}+{-# DEPRECATED withNumber "Use withScientific instead" #-}++-- | @withScientific expected f value@ applies @f@ to the 'Scientific' number when @value@ is a 'Number'.+-- and fails using @'typeMismatch' expected@ otherwise.+withScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a+withScientific _ f (Number scientific) = f scientific+withScientific expected _ v = typeMismatch expected v+{-# INLINE withScientific #-}++-- | @withBool expected f value@ applies @f@ to the 'Bool' when @value@ is a @Bool@+-- and fails using @'typeMismatch' expected@ otherwise.+withBool :: String -> (Bool -> Parser a) -> Value -> Parser a+withBool _ f (Bool arr) = f arr+withBool expected _ v = typeMismatch expected v+{-# INLINE withBool #-}++-- | Construct a 'Pair' from a key and a value.+(.=) :: ToJSON a => Text -> a -> Pair+name .= value = (name, toJSON value)+{-# INLINE (.=) #-}++-- | Convert a value from JSON, failing if the types do not match.+fromJSON :: (FromJSON a) => Value -> Result a+fromJSON = parse parseJSON+{-# INLINE fromJSON #-}++-- | Retrieve the value associated with the given key of an 'Object'.+-- The result is 'empty' if the key is not present or the value cannot+-- be converted to the desired type.+--+-- This accessor is appropriate if the key and value /must/ be present+-- in an object for it to be valid. If the key and value are+-- optional, use '(.:?)' instead.+(.:) :: (FromJSON a) => Object -> Text -> Parser a+obj .: key = case H.lookup key obj of+ Nothing -> fail $ "key " ++ show key ++ " not present"+ Just v -> parseJSON v+{-# INLINE (.:) #-}++-- | Retrieve the value associated with the given key of an 'Object'.+-- The result is 'Nothing' if the key is not present, or 'empty' if+-- the value cannot be converted to the desired type.+--+-- This accessor is most useful if the key and value can be absent+-- from an object without affecting its validity. If the key and+-- value are mandatory, use '(.:)' instead.+(.:?) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)+obj .:? key = case H.lookup key obj of+ Nothing -> pure Nothing+ Just v -> parseJSON v+{-# INLINE (.:?) #-}++-- | Helper for use in combination with '.:?' to provide default+-- values for optional JSON object fields.+--+-- This combinator is most useful if the key and value can be absent+-- from an object without affecting its validity and we know a default+-- value to assign in that case. If the key and value are mandatory,+-- use '(.:)' instead.+--+-- Example usage:+--+-- @ v1 <- o '.:?' \"opt_field_with_dfl\" .!= \"default_val\"+-- v2 <- o '.:' \"mandatory_field\"+-- v3 <- o '.:?' \"opt_field2\"+-- @+(.!=) :: Parser (Maybe a) -> a -> Parser a+pmval .!= val = fromMaybe val <$> pmval+{-# INLINE (.!=) #-}++-- | Fail parsing due to a type mismatch, with a descriptive message.+typeMismatch :: String -- ^ The name of the type you are trying to parse.+ -> Value -- ^ The actual value encountered.+ -> Parser a+typeMismatch expected actual =+ fail $ "when expecting a " ++ expected ++ ", encountered " ++ name +++ " instead"+ where+ name = case actual of+ Object _ -> "Object"+ Array _ -> "Array"+ String _ -> "String"+ Number _ -> "Number"+ Bool _ -> "Boolean"+ Null -> "Null"++scientificToNumber :: Scientific -> Number+scientificToNumber s+ | e < 0 = D $ realToFrac s+ | otherwise = I $ c * 10 ^ e+ where+ e = Scientific.base10Exponent s+ c = Scientific.coefficient s+{-# INLINE scientificToNumber #-}
Data/Aeson/Types/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, DeriveDataTypeable, Rank2Types #-}+{-# LANGUAGE CPP, DeriveDataTypeable, GeneralizedNewtypeDeriving, Rank2Types #-} -- | -- Module: Data.Aeson.Types.Internal@@ -35,17 +35,28 @@ , SumEncoding(..) , defaultOptions , defaultTaggedObject++ -- * Used for changing CamelCase names into something else.+ , camelTo++ -- * Other types+ , DotNetTime(..) ) where + import Control.Applicative import Control.Monad import Control.DeepSeq (NFData(..))-import Data.Attoparsec.Char8 (Number(..))+import Data.Char (toLower, isUpper)+import Data.Scientific (Scientific) import Data.Hashable (Hashable(..))+import Data.Data (Data) import Data.HashMap.Strict (HashMap) import Data.Monoid (Monoid(..)) import Data.String (IsString(..)) import Data.Text (Text, pack)+import Data.Time (UTCTime)+import Data.Time.Format (FormatTime) import Data.Typeable (Typeable) import Data.Vector (Vector) import qualified Data.HashMap.Strict as H@@ -166,16 +177,27 @@ data Value = Object !Object | Array !Array | String !Text- | Number !Number+ | Number !Scientific | Bool !Bool | Null- deriving (Eq, Show, Typeable)+ deriving (Eq, Show, Typeable, Data) +-- | A newtype wrapper for 'UTCTime' that uses the same non-standard+-- serialization format as Microsoft .NET, whose @System.DateTime@+-- type is by default serialized to JSON as in the following example:+--+-- > /Date(1302547608878)/+--+-- The number represents milliseconds since the Unix epoch.+newtype DotNetTime = DotNetTime {+ fromDotNetTime :: UTCTime+ } deriving (Eq, Ord, Read, Show, Typeable, FormatTime)+ instance NFData Value where rnf (Object o) = rnf o rnf (Array a) = V.foldl' (\x y -> rnf y `seq` x) () a rnf (String s) = rnf s- rnf (Number n) = case n of I i -> rnf i; D d -> rnf d+ rnf (Number n) = rnf n rnf (Bool b) = rnf b rnf Null = () @@ -183,17 +205,18 @@ fromString = String . pack {-# INLINE fromString #-} +hashValue :: Int -> Value -> Int+hashValue s (Object o) = H.foldl' hashWithSalt+ (s `hashWithSalt` (0::Int)) o+hashValue s (Array a) = V.foldl' hashWithSalt+ (s `hashWithSalt` (1::Int)) a+hashValue s (String str) = s `hashWithSalt` (2::Int) `hashWithSalt` str+hashValue s (Number n) = s `hashWithSalt` (3::Int) `hashWithSalt` n+hashValue s (Bool b) = s `hashWithSalt` (4::Int) `hashWithSalt` b+hashValue s Null = s `hashWithSalt` (5::Int)+ instance Hashable Value where- hashWithSalt s (Object o) = H.foldl' hashWithSalt- (s `hashWithSalt` (0::Int)) o- hashWithSalt s (Array a) = V.foldl' hashWithSalt- (s `hashWithSalt` (1::Int)) a- hashWithSalt s (String str) = s `hashWithSalt` (2::Int) `hashWithSalt` str- hashWithSalt s (Number n) = 3 `hashWithSalt`- case n of I i -> hashWithSalt s i- D d -> hashWithSalt s d- hashWithSalt s (Bool b) = s `hashWithSalt` (4::Int) `hashWithSalt` b- hashWithSalt s Null = s `hashWithSalt` (5::Int)+ hashWithSalt = hashValue -- | The empty array. emptyArray :: Value@@ -328,3 +351,24 @@ { tagFieldName = "tag" , contentsFieldName = "contents" }++-- | Converts from CamelCase to another lower case, interspersing+-- the character between all capital letters and their previous+-- entries, except those capital letters that appear together,+-- like 'API'.+--+-- For use by Aeson template haskell calls.+--+-- > camelTo '_' 'CamelCaseAPI' == "camel_case_api"+camelTo :: Char -> String -> String+camelTo c = lastWasCap True+ where+ lastWasCap :: Bool -- ^ Previous was a capital letter+ -> String -- ^ The remaining string+ -> String+ lastWasCap _ [] = []+ lastWasCap prev (x : xs) = if isUpper x+ then if prev+ then toLower x : lastWasCap True xs+ else c : toLower x : lastWasCap True xs+ else x : lastWasCap False xs
aeson.cabal view
@@ -1,5 +1,5 @@ name: aeson-version: 0.6.2.1+version: 0.7.0.0 license: BSD3 license-file: LICENSE category: Text, Web, JSON@@ -8,7 +8,7 @@ author: Bryan O'Sullivan <bos@serpentine.com> maintainer: Bryan O'Sullivan <bos@serpentine.com> stability: experimental-tested-with: GHC == 6.12.3, GHC == 7.0.4, GHC == 7.2.2+tested-with: GHC == 7.0, GHC == 7.2, GHC == 7.4, GHC == 7.6 synopsis: Fast JSON parsing and encoding cabal-version: >= 1.8 homepage: https://github.com/bos/aeson@@ -21,59 +21,41 @@ To get started, see the documentation for the @Data.Aeson@ module below. .- For release notes, see- <https://github.com/bos/aeson/blob/master/release-notes.markdown>- .- Parsing performance on a late 2010 MacBook Pro (2.66GHz Core i7),- for mostly-English tweets from Twitter's JSON search API:- .- * 0.8 KB, 32-bit GHC 6.12.3: 30538 msg\/sec (24.9 MB\/sec)- .- * 0.8 KB, 64-bit GHC 7.0.3: 31204 msg\/sec (25.4 MB\/sec)- .- * 6.4 KB, 32-bit GHC 6.12.3: 6731 msg\/sec (42.3 MB\/sec)- .- * 6.4 KB, 64-bit GHC 7.0.3: 6627 msg\/sec (41.7 MB\/sec)- .- * 11.8 KB, 32-bit GHC 6.12.3: 3751 msg\/sec (43.2 MB\/sec)+ Parsing performance on an early 2011 MacBook Pro (2.2GHz Core i7),+ running 64-bit GHC 7.6.3, for mostly-English tweets from Twitter's+ JSON search API: .- * 11.8 KB, 64-bit GHC 7.0.3: 3381 msg\/sec (38.9 MB\/sec)+ * 0.8 KB: 34124 msg\/sec (27.8 MB\/sec) .- * 31.2 KB, 32-bit GHC 6.12.3: 1306 msg\/sec (39.8 MB\/sec)+ * 6.4 KB: 6833 msg\/sec (43.0 MB\/sec) .- * 31.2 KB, 64-bit GHC 7.0.3: 1132 msg\/sec (34.5 MB\/sec)+ * 11.8 KB: 3410 msg\/sec (39.2 MB\/sec) .- * 61.5 KB, 32-bit GHC 6.12.3: 616 msg\/sec (37.0 MB\/sec)+ * 31.2 KB: 1157 msg\/sec (35.3 MB\/sec) .- * 61.5 KB, 64-bit GHC 7.0.3: 534 msg\/sec (32.1 MB\/sec)+ * 61.5 KB: 542 msg\/sec (32.5 MB\/sec) . Handling heavily-escaped text is a little more work. Here is parsing performance with Japanese tweets, where much of the text is entirely Unicode-escaped. .- * 14.6 KB, 32-bit GHC 6.12.3: 2315 msg\/sec (33.1 MB\/sec)- .- * 14.6 KB, 64-bit GHC 7.0.3: 1986 msg\/sec (28.4 MB\/sec)- .- * 44.1 KB, 32-bit GHC 6.12.3: 712 msg\/sec (30.7 MB\/sec)- .- * 44.1 KB, 64-bit GHC 7.0.3: 634 msg\/sec (27.3 MB\/sec)+ * 14.6 KB: 2101 msg\/sec (30.0 MB\/sec) .- * 82.9 KB, 32-bit GHC 6.12.3: 377 msg\/sec (30.5 MB\/sec)+ * 44.1 KB: 667 msg\/sec (28.7 MB\/sec) .- * 82.9 KB, 64-bit GHC 7.0.3: 332 msg\/sec (26.9 MB\/sec)+ * 82.9 KB: 360 msg\/sec (29.2 MB\/sec) . Encoding performance on the same machine and data: .- * English, 854 bytes: 43439 msg\/sec (35.4 MB/sec)+ * English, 0.8 KB: 109697 msg\/sec (89.3 MB\/sec) .- * English, 6.4 KB: 7127 msg\/sec (44.8 MB/sec)+ * English, 6.4 KB: 18517 msg\/sec (116.4 MB\/sec) .- * Engish, 61.5 KB: 765 msg\/sec (46.0 MB/sec)+ * Engish, 61.5 KB: 1963 msg\/sec (118.0 MB\/sec) .- * Japanese, 14.6 KB: 4727 msg\/sec (67.5 MB/sec)+ * Japanese, 14.6 KB: 12140 msg\/sec (173.5 MB\/sec) .- * Japanese, 44.1 KB: 1505 msg\/sec (64.8 MB/sec)+ * Japanese, 44.1 KB: 3980 msg\/sec (171.3 MB\/sec) . (A note on naming: in Greek mythology, Aeson was the father of Jason.) @@ -84,13 +66,21 @@ benchmarks/*.py benchmarks/Makefile benchmarks/json-data/*.json+ changelog examples/*.hs- release-notes.markdown flag developer description: operate in developer mode default: False +flag blaze-builder+ description: Use blaze-builder instead of bytestring >= 0.10+ default: False++flag new-bytestring-builder+ description: Use the new bytestring builder available in bytestring >= 0.10.4.0+ default: False+ library exposed-modules: Data.Aeson@@ -104,8 +94,17 @@ Data.Aeson.Functions Data.Aeson.Parser.Internal Data.Aeson.Types.Class+ Data.Aeson.Types.Instances Data.Aeson.Types.Internal + if flag(new-bytestring-builder)+ other-modules: Data.Aeson.Encode.ByteString+ build-depends: bytestring >= 0.10.4.0,+ text >= 1.1.0.0+ else+ build-depends: bytestring < 0.10.4.0,+ text >= 0.11.1.0+ if impl(ghc >= 7.2.1) cpp-options: -DGENERICS build-depends: ghc-prim >= 0.2, dlist >= 0.2@@ -113,10 +112,8 @@ Data.Aeson.Types.Generic build-depends:- attoparsec >= 0.8.6.1,+ attoparsec >= 0.11.1.0, base == 4.*,- blaze-builder >= 0.2.1.4,- bytestring, containers, deepseq, hashable >= 1.1.2.0,@@ -124,11 +121,17 @@ old-locale, syb, template-haskell >= 2.4,- text >= 0.11.1.0, time, unordered-containers >= 0.1.3.0,- vector >= 0.7.1+ vector >= 0.7.1,+ scientific >= 0.2 + if flag(blaze-builder)+ build-depends: blaze-builder >= 0.2.1.4+ cpp-options: -DUSE_BLAZE_BUILDER+ else+ build-depends: bytestring >= 0.10+ if flag(developer) ghc-options: -Werror ghc-prof-options: -auto-all@@ -139,12 +142,13 @@ type: exitcode-stdio-1.0 hs-source-dirs: tests main-is: Properties.hs- other-modules: Functions- Instances- Types- Options- Encoders- Properties.Deprecated+ other-modules:+ Encoders+ Functions+ Instances+ Options+ Properties.Deprecated+ Types ghc-options: -Wall -threaded -rtsopts@@ -163,6 +167,8 @@ template-haskell, test-framework, test-framework-quickcheck2,+ test-framework-hunit,+ HUnit, text, time, unordered-containers,
benchmarks/AesonEncode.hs view
@@ -3,7 +3,8 @@ import Control.Exception import Control.Monad import Data.Aeson-import Data.Attoparsec+import Data.Attoparsec (IResult(..), parseWith)+import Data.Char (isDigit) import Data.Time.Clock import System.Environment (getArgs) import System.IO@@ -22,7 +23,10 @@ main :: IO () main = do- (cnt:args) <- getArgs+ args0 <- getArgs+ let (cnt,args) = case args0 of+ (i:c:a) | all isDigit i && all isDigit c -> (c,a)+ (c:a) -> (c,a) let count = read cnt :: Int forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do putStrLn $ arg ++ ":"@@ -39,5 +43,5 @@ loop 0 r0 delta <- flip diffUTCTime start `fmap` getCurrentTime let rate = fromIntegral count / realToFrac delta :: Double- putStrLn $ " " ++ show delta+ putStrLn $ " " ++ cnt ++ " good, " ++ show delta putStrLn $ " " ++ show (round rate :: Int) ++ " per second"
benchmarks/AesonParse.hs view
@@ -3,12 +3,13 @@ import Control.Exception import Control.Monad import Data.Aeson-import Data.Attoparsec+import Data.Attoparsec (IResult(..), parseWith) import Data.Time.Clock import System.Environment (getArgs) import System.IO import qualified Data.ByteString as B +main :: IO () main = do (bs:cnt:args) <- getArgs let count = read cnt :: Int@@ -23,10 +24,10 @@ let refill = B.hGet h blkSize result <- parseWith refill json =<< refill case result of- Done _ r -> loop (good+1) bad+ Done _ _ -> loop (good+1) bad _ -> loop good (bad+1) (good, _) <- loop 0 0 delta <- flip diffUTCTime start `fmap` getCurrentTime putStrLn $ " " ++ show good ++ " good, " ++ show delta let rate = fromIntegral count / realToFrac delta :: Double- putStrLn $ " " ++ show (round rate) ++ " per second"+ putStrLn $ " " ++ show (round rate :: Int) ++ " per second"
benchmarks/CompareWithJSON.hs view
@@ -5,9 +5,13 @@ import Blaze.ByteString.Builder.Char.Utf8 (fromString) import Control.DeepSeq (NFData(rnf)) import Criterion.Main+import qualified Data.Aeson.Encode as A import qualified Data.Aeson as A import qualified Data.ByteString.Lazy as BL import qualified Text.JSON as J+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.Encoding as TLE #if !MIN_VERSION_bytestring(0,10,0) import qualified Data.ByteString.Lazy.Internal as BL@@ -42,6 +46,14 @@ encodeJ :: J.JSValue -> BL.ByteString encodeJ = toLazyByteString . fromString . J.encode +#if MIN_VERSION_bytestring(0,10,4)+encodeToText :: A.Value -> TL.Text+encodeToText = TLB.toLazyText . A.encodeToTextBuilder . A.toJSON++encodeViaText :: A.Value -> BL.ByteString+encodeViaText = TLE.encodeUtf8 . encodeToText+#endif+ main :: IO () main = do let enFile = "json-data/twitter100.json"@@ -63,11 +75,19 @@ ] , bgroup "encode" [ bgroup "en" [- bench "aeson" $ nf A.encode (decodeA enA)+ bench "aeson-to-bytestring" $ nf A.encode (decodeA enA)+#if MIN_VERSION_bytestring(0,10,4)+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA enA)+ , bench "aeson-to-text" $ nf encodeToText (decodeA enA)+#endif , bench "json" $ nf encodeJ (decodeJ enJ) ] , bgroup "jp" [- bench "aeson" $ nf A.encode (decodeA jpA)+ bench "aeson-to-bytestring" $ nf A.encode (decodeA jpA)+#if MIN_VERSION_bytestring(0,10,4)+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA jpA)+ , bench "aeson-to-text" $ nf encodeToText (decodeA jpA)+#endif , bench "json" $ nf encodeJ (decodeJ jpJ) ] ]
benchmarks/JsonParse.hs view
@@ -6,7 +6,6 @@ import Text.JSON import Data.Time.Clock import System.Environment (getArgs)-import System.IO instance NFData JSValue where rnf JSNull = ()@@ -16,6 +15,7 @@ rnf (JSArray vs) = rnf vs rnf (JSObject kvs) = rnf (fromJSObject kvs) +main :: IO () main = do (cnt:args) <- getArgs let count = read cnt :: Int@@ -27,7 +27,7 @@ | otherwise = do s <- readFile arg case decodeStrict s of- Ok (v::JSValue) -> loop (good+1) 0+ Ok (_::JSValue) -> loop (good+1) 0 _ -> loop 0 (bad+1) (good, _) <- loop 0 0 end <- getCurrentTime
benchmarks/aeson-benchmarks.cabal view
@@ -6,25 +6,26 @@ executable aeson-benchmark-compare-with-json main-is: CompareWithJSON.hs- ghc-options: -Wall -O2+ ghc-options: -Wall -O2 -rtsopts build-depends: aeson, base, blaze-builder, bytestring, criterion,- json+ json,+ text executable aeson-benchmark-aeson-encode main-is: AesonEncode.hs- ghc-options: -Wall -O2+ ghc-options: -Wall -O2 -rtsopts build-depends: aeson, base executable aeson-benchmark-aeson-parse main-is: AesonParse.hs- ghc-options: -Wall -O2+ ghc-options: -Wall -O2 -rtsopts build-depends: aeson, attoparsec,@@ -32,7 +33,7 @@ executable aeson-benchmark-json-parse main-is: JsonParse.hs- ghc-options: -Wall -O2+ ghc-options: -Wall -O2 -rtsopts build-depends: base, deepseq,
benchmarks/bench-parse.py view
@@ -7,11 +7,12 @@ if len(sys.argv) > 1: parser_exe = sys.argv[1] else:- parser_exe = './AesonParse'+ parser_exe = ('dist/build/aeson-benchmark-aeson-parse/' ++ 'aeson-benchmark-aeson-parse') def run(count, filename): print ' %s :: %s times' % (filename, count)- p = subprocess.Popen([parser_exe, str(count), filename],+ p = subprocess.Popen([parser_exe, '65536', str(count), filename], stdout=subprocess.PIPE) output = p.stdout.read() p.wait()
benchmarks/encode.py view
@@ -2,6 +2,16 @@ import json, sys, time +def isint(x):+ try:+ int(x)+ return True+ except:+ return False++if len(sys.argv) > 2 and isint(sys.argv[1]) and isint(sys.argv[2]):+ sys.argv.pop(1)+ count = int(sys.argv[1]) for n in sys.argv[2:]:@@ -11,4 +21,4 @@ for i in xrange(count): json.dumps(obj) end = time.time()- print ' ', end - start+ print ' %d good, %gs' % (count, end - start)
+ benchmarks/json-data/geometry.json view
@@ -0,0 +1,1 @@+{"geometry": {"type": "Polygon", "coordinates": [[[-0.939359853061118, 51.57401065198471], [-0.939440892477492, 51.57431080772057], [-0.939543636564569, 51.57460846194951], [-0.939564627628489, 51.574822653966265], [-0.939763179055758, 51.575406210178826], [-0.939787182642249, 51.575552991614], [-0.939819571231525, 51.57564949527348], [-0.939851290904264, 51.57571272360808], [-0.939975682132949, 51.57588648747347], [-0.940036822193859, 51.57598774653439], [-0.940072640734852, 51.57606090267849], [-0.940109693338918, 51.576205104339515], [-0.940125502187331, 51.57645611534466], [-0.940118623499009, 51.57662779459441], [-0.94008851367835, 51.57680555827417], [-0.939998015208524, 51.57709787034017], [-0.939928028667517, 51.577252794653916], [-0.939830628174189, 51.57740747134858], [-0.939796941313687, 51.57749078985784], [-0.939785586773343, 51.57754463746666], [-0.939770656147318, 51.57769016804059], [-0.939658154074368, 51.57824573765943], [-0.939485738834128, 51.57883313597966], [-0.93945717030888, 51.579192545519916], [-0.939524336079755, 51.57928306919007], [-0.939540939284811, 51.57931379092206], [-0.939553921057406, 51.579748206813974], [-0.939549110634237, 51.57983088690364], [-0.939520940649101, 51.58004913048237], [-0.93951863934971, 51.58014801827346], [-0.939525037302583, 51.580245186310094], [-0.939540364690294, 51.58033074581249], [-0.939561798495469, 51.58040197377017], [-0.939594984852117, 51.58046431619436], [-0.939708262827559, 51.580619996404984], [-0.939729069878358, 51.58065615108302], [-0.939759224390201, 51.58072476025555], [-0.939813615319267, 51.58093026195459], [-0.939900523550716, 51.58172321441459], [-0.939894144544868, 51.581997403240464], [-0.939910832471369, 51.58208657162566], [-0.940114353648015, 51.582457967531546], [-0.94022333049887, 51.58267475179605], [-0.940267247821581, 51.58277225843995], [-0.94038427828014, 51.583077233742756], [-0.940493362377966, 51.583289522851196], [-0.940571515796737, 51.58340442254201], [-0.940725857371931, 51.58359464061899], [-0.941198340240742, 51.584069167875626], [-0.941335307610427, 51.584261925920295], [-0.941372786463165, 51.5843261048293], [-0.941416540699353, 51.58443080287741], [-0.941461326187118, 51.584739621364996], [-0.941517445876004, 51.5849954910945], [-0.941575869597484, 51.58533860085252], [-0.941574762730556, 51.58538624677686], [-0.941565185406358, 51.58542572382202], [-0.941550002863301, 51.58545795698674], [-0.941515976834126, 51.58549361692739], [-0.941470510606583, 51.585524677868065], [-0.941423872780384, 51.585544039043356], [-0.94131509921043, 51.585566436558274], [-0.941075026707647, 51.58558675057684], [-0.940953181611661, 51.58561262652464], [-0.940734943851404, 51.58568708689612], [-0.940229533088359, 51.585883040066975], [-0.940067635923264, 51.58595531027499], [-0.939917220191166, 51.58603038143916], [-0.939797255285709, 51.586099433232604], [-0.939675637701456, 51.586177461657186], [-0.939611074554604, 51.58622273608784], [-0.939340396866166, 51.586441486256], [-0.93912244296424, 51.58662744303347], [-0.938817233975319, 51.58671729893312], [-0.938661522913105, 51.586771639765516], [-0.938087678078033, 51.586992141762096], [-0.937332636663603, 51.5873072119485], [-0.93492634290483, 51.58836081134952], [-0.934774110277819, 51.58845114531925], [-0.934663126573178, 51.588505886685766], [-0.934565467487243, 51.588546362183585], [-0.934462140700832, 51.588582290320545], [-0.934337145222589, 51.58861892084846], [-0.934213782000904, 51.588647473549656], [-0.934055887760941, 51.588671216763295], [-0.933259701136762, 51.58864510257983], [-0.933213278816969, 51.588716614209304], [-0.932681740160827, 51.588792708227174], [-0.931992471253759, 51.58900853446031], [-0.930629113767652, 51.58946908647644], [-0.928525036745892, 51.59005953842682], [-0.928533690860491, 51.59024394687689], [-0.928456010745829, 51.59047792078815], [-0.928256501298223, 51.5906748158337], [-0.927916132025856, 51.59066181734799], [-0.927671608556404, 51.590624516635486], [-0.927319567022116, 51.59061680481465], [-0.926850285435352, 51.59062240702726], [-0.926313746570405, 51.59066425819173], [-0.925516790702947, 51.59079184232522], [-0.925387133168341, 51.59078076476673], [-0.925293323156809, 51.59077990606886], [-0.925202187496562, 51.59078806346173], [-0.925112304116411, 51.59080432476366], [-0.925036768134577, 51.59082431403807], [-0.924968299737815, 51.59085066215826], [-0.924899640304234, 51.59088510100373], [-0.924851228495836, 51.590917926896914], [-0.924734051019008, 51.59105082982951], [-0.924694255912291, 51.59108553291224], [-0.924446018071168, 51.59126668934789], [-0.924204972773907, 51.59150995377465], [-0.923492520665307, 51.59215352189589], [-0.922775141969353, 51.59288246146081], [-0.922298613651092, 51.59343737077436], [-0.922101568270595, 51.59365046303728], [-0.92149319027045, 51.59422483935332], [-0.921029930136652, 51.59464499018023], [-0.919455791303858, 51.595519790418045], [-0.919908472816787, 51.59560757835559], [-0.919902358174605, 51.595621908790214], [-0.919721503870405, 51.59588190272939], [-0.919513222918683, 51.59614164398608], [-0.919057326435374, 51.59661490568889], [-0.918991959815932, 51.59669253146064], [-0.918853979663433, 51.59690975873926], [-0.91882720841051, 51.59694278142396], [-0.918711889332325, 51.597056812913756], [-0.918614808732714, 51.59713234806153], [-0.918297245740306, 51.59749448485627], [-0.918073703114389, 51.59778825130676], [-0.917853804369843, 51.59811082427763], [-0.917772408698363, 51.59831598343439], [-0.917709563771812, 51.59853030520902], [-0.917692745480418, 51.59856971355161], [-0.917634249201942, 51.59866178857289], [-0.917443039919903, 51.59887043094418], [-0.917335250471836, 51.598971042984616], [-0.916888284039272, 51.599309503426845], [-0.916921110547038, 51.59938623548714], [-0.916942485633783, 51.5995195094582], [-0.916937652924948, 51.599601289122916], [-0.916945811778801, 51.599683188627004], [-0.916964246289877, 51.599757989575366], [-0.917049297107238, 51.59994580090974], [-0.917089705367533, 51.60000731699611], [-0.917171120773417, 51.60010517795964], [-0.91752823274465, 51.60044925531009], [-0.917834023417531, 51.600765883511485], [-0.917913079603466, 51.600902386385464], [-0.918033251654948, 51.60107073894696], [-0.91851090277833, 51.601507638962644], [-0.918694916056997, 51.601663091331545], [-0.919167224655989, 51.60214309940451], [-0.919302231291783, 51.6024167896932], [-0.919552009673002, 51.60266096432073], [-0.919812571846437, 51.60293760761218], [-0.920091738726093, 51.60358667644501], [-0.920208566517809, 51.603592246724574], [-0.920644522919282, 51.60359715428394], [-0.921093152621479, 51.6036156641763], [-0.921168285587618, 51.603613657034074], [-0.921469264587163, 51.6035867495928], [-0.921584776688781, 51.603586911416876], [-0.921718864440287, 51.603595336217005], [-0.921999521996191, 51.60363387995426], [-0.922136050325758, 51.603661209181794], [-0.922248015684399, 51.60368921195661], [-0.922346882036963, 51.60372159023333], [-0.922478548042792, 51.60377135359644], [-0.922605777045377, 51.603825571929555], [-0.92269948345521, 51.60389297005248], [-0.922855181916126, 51.60396453348124], [-0.922908065211369, 51.60398749776935], [-0.923525984356841, 51.604174796116844], [-0.923689774691443, 51.6042095667925], [-0.923842334751645, 51.60423074681459], [-0.924020987014581, 51.604247669912816], [-0.924152253615336, 51.604253368572344], [-0.924379056519158, 51.60424915231234], [-0.924491916632975, 51.60423939614583], [-0.925129396784027, 51.604149022807746], [-0.925308707040747, 51.60413807581467], [-0.925396812395019, 51.604137083863186], [-0.925816640142735, 51.60415261457396], [-0.926339243350925, 51.604157394450915], [-0.926627592983669, 51.60417621577326], [-0.928219342008724, 51.60433911850777], [-0.928540897883304, 51.60435823822504], [-0.928666454251138, 51.6043611822271], [-0.928925123731038, 51.60435275210506], [-0.929272427371303, 51.60432085222454], [-0.929350681081097, 51.604308977474346], [-0.929525019586135, 51.60426381040009], [-0.929730308556221, 51.60419195021111], [-0.929806393059037, 51.60414948374236], [-0.929854111423592, 51.60408517871234], [-0.929877477717563, 51.604012559228565], [-0.929880189120251, 51.60395863398061], [-0.930157001898001, 51.603362311928585], [-0.930233415197893, 51.60324431822904], [-0.930397156019029, 51.60303540508514], [-0.93058677482955, 51.602831223239896], [-0.930747612253953, 51.60268432562219], [-0.931065151604954, 51.602443542878724], [-0.931358556224333, 51.60224659876122], [-0.931494751600125, 51.602165114969594], [-0.931807666849096, 51.601998019766675], [-0.932115553298882, 51.60186055047904], [-0.932344261944379, 51.601774512081256], [-0.932581062209752, 51.601712824287226], [-0.932837650566022, 51.60166929919289], [-0.93304760157037, 51.60164423223924], [-0.933247236692325, 51.60162806284857], [-0.933524572231589, 51.601623388892406], [-0.93367307135076, 51.60163283011416], [-0.933854562367985, 51.601651562386515], [-0.934222940436163, 51.60170526005669], [-0.934582321335698, 51.60177326158339], [-0.935176916778695, 51.60190903449902], [-0.935323237909383, 51.60194992468383], [-0.935449328012611, 51.60199153042619], [-0.935555166022244, 51.60203475076641], [-0.935754957696255, 51.60213547009268], [-0.935920944220561, 51.60219991608389], [-0.936105992086264, 51.60225194623237], [-0.936251123590137, 51.60228203448254], [-0.9362553703842, 51.602285669620606], [-0.935954861941404, 51.603034649313756], [-0.936025513047831, 51.60328615677915], [-0.937604653681525, 51.60374194595848], [-0.937842729718605, 51.6037494948452], [-0.937998245297976, 51.60376798569096], [-0.938149157504488, 51.60379812385097], [-0.938282536474463, 51.60383709493093], [-0.938398403200176, 51.60388400001471], [-0.938549544157173, 51.60396629131982], [-0.938542113846477, 51.60403725821696], [-0.938540670189083, 51.60403724516617], [-0.938690470772444, 51.60417707075241], [-0.93885671831091, 51.60429276731543], [-0.938949655717409, 51.60433227129961], [-0.939171393952754, 51.60435945147724], [-0.939491406642938, 51.60438302306183], [-0.939580914110842, 51.60438383145672], [-0.939698081584302, 51.604374998744255], [-0.939860253923854, 51.60435578228165], [-0.940131370864495, 51.60430877574863], [-0.940224037565311, 51.60429792302206], [-0.941065905352937, 51.604358569226044], [-0.941456261791824, 51.60439985396626], [-0.94172260946072, 51.604433725629356], [-0.942065117075164, 51.604483568721975], [-0.942405972956444, 51.60454238758566], [-0.942542307804962, 51.60457868292929], [-0.942668453620936, 51.60461848302318], [-0.942754322773386, 51.60465162617505], [-0.942930037674105, 51.6047332338937], [-0.94300827141212, 51.60478429141865], [-0.943050642772121, 51.60482513526179], [-0.943095505071305, 51.604883085645305], [-0.943175837511794, 51.60503037259752], [-0.943199044776033, 51.60508812802956], [-0.943264927978451, 51.605360268787045], [-0.94328295289835, 51.6055168856955], [-0.943285556153251, 51.605653582182974], [-0.94327790338372, 51.60573443814757], [-0.943262026480571, 51.60579633763445], [-0.943228365851772, 51.605877858692274], [-0.943092212068021, 51.60614458434088], [-0.943074097962666, 51.60624063192375], [-0.943061365824471, 51.606415854446915], [-0.943044862244347, 51.60650472320056], [-0.943017897594943, 51.606608783583646], [-0.942979591589439, 51.606703750216774], [-0.942905884027612, 51.60683076806164], [-0.942741267849139, 51.60707925374213], [-0.942655006715899, 51.607249318295594], [-0.942630361430127, 51.60731563455148], [-0.942616263944651, 51.607425205688976], [-0.942621958529523, 51.60749089598715], [-0.942636336634899, 51.60755576531453], [-0.942660904708633, 51.607617129739225], [-0.942696981288364, 51.607680396114986], [-0.942747433102709, 51.60774648940761], [-0.942856244975984, 51.6078490746924], [-0.94299552290573, 51.60794563997599], [-0.943040847342192, 51.60798381288104], [-0.943186973159248, 51.608158666884215], [-0.943285889122319, 51.60825217104693], [-0.943509689787491, 51.60844031193307], [-0.94379690141149, 51.609007570967925], [-0.943824004868445, 51.60908424372538], [-0.943831400135399, 51.609201201602104], [-0.943839541642426, 51.60922375393887], [-0.943852077204152, 51.6092436483043], [-0.943874740412961, 51.60926273459518], [-0.943900416430683, 51.60927645299323], [-0.944008015202393, 51.60930709311221], [-0.944074894993692, 51.60934995527111], [-0.944126815315737, 51.60941516198104], [-0.944143328071964, 51.60945037786937], [-0.944150844233183, 51.609499899486615], [-0.944148608042361, 51.60953404761941], [-0.944074023202655, 51.60969882315075], [-0.94403415265091, 51.60986121332522], [-0.944017357658548, 51.60996266784037], [-0.943992023164905, 51.61030771903426], [-0.943965568458423, 51.61051428886229], [-0.943938629028152, 51.61067949277199], [-0.943919488028492, 51.61075754789674], [-0.943885949921455, 51.61083367520212], [-0.943827406881077, 51.61092935920088], [-0.943739589608875, 51.61104186395993], [-0.943638735204063, 51.61115604969767], [-0.943533757272514, 51.611261206608894], [-0.942952360107171, 51.61179457356613], [-0.942768364001955, 51.61194397664764], [-0.942436714102017, 51.61217027698273], [-0.942010518369458, 51.61248743929258], [-0.941742162181165, 51.61266215641604], [-0.941369087685306, 51.61286829880399], [-0.941218061678922, 51.612965845186196], [-0.941055044244821, 51.613082165678385], [-0.940962318642569, 51.61315685920963], [-0.940802313735133, 51.613329853845215], [-0.940532273923746, 51.613638528438315], [-0.940201080800705, 51.61403027273604], [-0.940058816377521, 51.614185443187054], [-0.939985695447699, 51.614286388653916], [-0.939953592073967, 51.614362527773245], [-0.939906859457064, 51.614508669589505], [-0.939802341993177, 51.61490335803689], [-0.939554942446072, 51.615603370947234], [-0.939452722231603, 51.61596121406953], [-0.939421935085161, 51.61604275989804], [-0.939387192811998, 51.616108085051245], [-0.939207265482904, 51.61639149465681], [-0.939036585027605, 51.61671185322904], [-0.938852844916865, 51.61697274874371], [-0.938765881571911, 51.61710953487875], [-0.938636321443754, 51.617400592062225], [-0.93858227703968, 51.617550263869646], [-0.938563060896774, 51.61763101488344], [-0.938557821588965, 51.617793716095726], [-0.938568952285691, 51.6178738422429], [-0.938586194898738, 51.61793963701825], [-0.93864824402059, 51.61806608070808], [-0.938712639101221, 51.61815388154161], [-0.938801458484915, 51.61824729803767], [-0.938902019778203, 51.61833272809444], [-0.939001577491258, 51.61839926656718], [-0.939080060597956, 51.6184404379885], [-0.939144458958051, 51.618466196342986], [-0.93924483456823, 51.61849767462955], [-0.939389936057716, 51.61853135511866], [-0.939533886937889, 51.618552436752374], [-0.939605967169062, 51.618558482633226], [-0.939704125343146, 51.618561167280205], [-0.940011869234288, 51.61855765138392], [-0.940970156479417, 51.61846828865034], [-0.942814559287174, 51.61834913395653], [-0.9433943585448, 51.61832378069166], [-0.943791844341078, 51.61831207069643], [-0.944095316626396, 51.61830580819228], [-0.944345189840605, 51.61830625638639], [-0.944633949874169, 51.618311549349706], [-0.944866264500346, 51.618321729423634], [-0.945069571918896, 51.61833704343469], [-0.945259736594118, 51.618358533188456], [-0.945405071369022, 51.6183823175338], [-0.945538707551366, 51.61841229079249], [-0.945670733169093, 51.618449442740584], [-0.945789657802543, 51.61849097274293], [-0.945898390514756, 51.618536007789324], [-0.946002624502939, 51.61858819565799], [-0.946144975691139, 51.61867849034559], [-0.946290660655923, 51.61881197458077], [-0.946424293873759, 51.618966930407886], [-0.94648587943588, 51.619052004215185], [-0.946597289998464, 51.61923103785771], [-0.946748500992991, 51.619500344620654], [-0.946865282768134, 51.619759451627154], [-0.94692090631825, 51.619852564183816], [-0.946986743272162, 51.619941272483025], [-0.947121992710119, 51.62008904866086], [-0.947221067183078, 51.620177155655796], [-0.947357337089385, 51.62028088174252], [-0.947636341593443, 51.62045871900467], [-0.947732020809812, 51.62050633282523], [-0.947832261440868, 51.62054409665008], [-0.948024909405708, 51.6205835873772], [-0.948272727755043, 51.62061098363029], [-0.94903310890345, 51.62064836261257], [-0.949342820854191, 51.62068530212313], [-0.949548509996597, 51.62072310869445], [-0.949603327033706, 51.620726296510135], [-0.94966121922192, 51.62072141934501], [-0.949725095662238, 51.62070760405018], [-0.949813979767225, 51.620674230793945], [-0.949850856696741, 51.620766275113425], [-0.949938127431095, 51.62092800552347], [-0.95012170684362, 51.62142328688538], [-0.950137689181391, 51.621481875301626], [-0.950144591409982, 51.621558365780544], [-0.950143525838059, 51.62166715485939], [-0.950086848280287, 51.62218276713024], [-0.950081566444785, 51.62234906486587], [-0.950091380322934, 51.6227375905417], [-0.950012857804674, 51.623198158520914], [-0.949963053357781, 51.62366617649237], [-0.94993621019599, 51.62382778558582], [-0.949887611273865, 51.62405573809743], [-0.94981748429385, 51.62434014525264], [-0.949698012983878, 51.6246969431444], [-0.949601071539472, 51.62520410239216], [-0.949519655994856, 51.62547671925938], [-0.949509640700394, 51.62553507516918], [-0.949509569744091, 51.62560071332227], [-0.949517625184728, 51.6256898023632], [-0.949539397678852, 51.62581048474923], [-0.949602831958219, 51.626066413978656], [-0.949622600072634, 51.6262113557699], [-0.949625807500304, 51.62644786389373], [-0.949588359660548, 51.62688092470566], [-0.949587162842075, 51.62718303218221], [-0.949593421398238, 51.627287390862], [-0.949641886384285, 51.62762860642186], [-0.949677564559904, 51.627772791296934], [-0.949732061930258, 51.62791534613564], [-0.949847071945823, 51.62812767746571], [-0.95005020451512, 51.62890367131774], [-0.949860358893705, 51.62924185674224], [-0.949849459019953, 51.62927592739189], [-0.949848649628705, 51.62931098742953], [-0.949857806222275, 51.62935243070728], [-0.949882540677514, 51.62940750068883], [-0.949782851646605, 51.62940750843079], [-0.949684104107472, 51.6296170289926], [-0.949619670293909, 51.62984214210067], [-0.949589348281571, 51.62990391300069], [-0.949478823262764, 51.63006027755304], [-0.949419643728549, 51.63018293320961], [-0.949378577882241, 51.63033452402259], [-0.949364251310331, 51.63051692549393], [-0.949339228920643, 51.63059942443184], [-0.949248633732607, 51.63076855530058], [-0.949181283974238, 51.630869557872636], [-0.949044504574139, 51.63103647701982], [-0.948893935504611, 51.63136242402941], [-0.948761069414249, 51.631297394415576], [-0.948669492362367, 51.63125880992652], [-0.948537801268757, 51.63120547966423], [-0.948447461288637, 51.63117589768262], [-0.948353982967507, 51.63115707745748], [-0.948302104865814, 51.63115121794117], [-0.948079606840815, 51.63115102360314], [-0.947964190602531, 51.63114369566099], [-0.94782149485015, 51.63112892992514], [-0.947725107052886, 51.63111098229264], [-0.947684910040859, 51.63109983219839], [-0.947483021604023, 51.63102069524269], [-0.947447137482345, 51.63101048287877], [-0.947306094892948, 51.630986739722026], [-0.947000710620611, 51.63094713644845], [-0.946674033898238, 51.6308911565172], [-0.946364247153943, 51.63079216747898], [-0.946230490849763, 51.63076579091048], [-0.946172752135344, 51.63076347450912], [-0.94612066649297, 51.630766603772976], [-0.945914796224295, 51.63079712600587], [-0.94583241748209, 51.63079818492752], [-0.945382953779145, 51.63067905708907], [-0.945085984219956, 51.63058827220451], [-0.944883205963743, 51.630547786680644], [-0.944304065189339, 51.630538086402446], [-0.94394898927073, 51.630523204990325], [-0.943611477254356, 51.63049858971805], [-0.943603681926519, 51.6307098224617], [-0.943277115569317, 51.63102249010073], [-0.943359247728321, 51.63109426279834], [-0.942862682241593, 51.631385618132356], [-0.942777562378065, 51.63144239822567], [-0.942532313252267, 51.63161282917167], [-0.942337892928893, 51.63177202827151], [-0.94226606523137, 51.631816339444626], [-0.942197377359527, 51.63184988892168], [-0.942115813951467, 51.631877927416205], [-0.941937005967162, 51.631924871353945], [-0.941512981586086, 51.63201636159427], [-0.94144898217334, 51.6320346671529], [-0.94125937051438, 51.632111184999914], [-0.940790185204025, 51.6323425346351], [-0.940501042462563, 51.632535943664614], [-0.940243238615803, 51.63268647504363], [-0.940131608045529, 51.632764593869275], [-0.939328651391563, 51.63361514453957], [-0.939011405652477, 51.634145481445906], [-0.93882930544315, 51.63451878632893], [-0.93850479164515, 51.63486472819315], [-0.93841585373771, 51.63483694950617], [-0.938308667759282, 51.63503379600045], [-0.938237520065274, 51.63511048065125], [-0.938174497877949, 51.635148574806536], [-0.938097155068085, 51.63518114448376], [-0.938014243480848, 51.63520467214815], [-0.937885103100742, 51.635227781700706], [-0.937899482630853, 51.63529265131639], [-0.937852791962712, 51.635312010611116], [-0.937756752174709, 51.63534081433219], [-0.93768849662133, 51.635355482713884], [-0.937445207164159, 51.63537845841074], [-0.937282775985471, 51.6354039635962], [-0.936848828519967, 51.635485456519916], [-0.935951432459366, 51.63561220386278], [-0.935719677036262, 51.635636179646525], [-0.935420148631615, 51.63565414571281], [-0.935249454884316, 51.63560044703531], [-0.935077590540852, 51.635535048401415], [-0.934717727795324, 51.63535285185533], [-0.934413155884105, 51.635216113905294], [-0.934240481559584, 51.635123731852076], [-0.934130824273522, 51.63505529964683], [-0.934018404467151, 51.63498144729724], [-0.93379675026591, 51.63482118293064], [-0.933679892303923, 51.6347517857655], [-0.933595523374065, 51.63471415412531], [-0.933350473747258, 51.63462740768713], [-0.933261876876166, 51.63458524160035], [-0.933052343088727, 51.63446285066096], [-0.932887751506176, 51.63439571653097], [-0.932638117941304, 51.63431971687678], [-0.932307197466639, 51.63419801967628], [-0.931343887912331, 51.63380981222079], [-0.931071830619705, 51.63376597498289], [-0.930956833347264, 51.63374065092008], [-0.930823331188951, 51.63370346918478], [-0.930701576222194, 51.633658301797674], [-0.930601553796263, 51.63361063468632], [-0.930506119022842, 51.63355221932683], [-0.930386739592999, 51.633467510133144], [-0.930286034494439, 51.633387466714524], [-0.930225334024314, 51.63332666999925], [-0.930188937852857, 51.633276884582266], [-0.930114567680391, 51.63312155131756], [-0.92999324620862, 51.63293521875163], [-0.929900400330813, 51.63282827174111], [-0.929602366751531, 51.6325378240622], [-0.929499431873266, 51.632429885607195], [-0.929341000864788, 51.63222433167361], [-0.929059923028374, 51.631889079042224], [-0.928963213558906, 51.63176231446386], [-0.928896162303318, 51.6316645934755], [-0.928844852932023, 51.631573310156845], [-0.928688841592085, 51.63126527289447], [-0.928672375509884, 51.6312282570475], [-0.928615004479859, 51.631026321392014], [-0.928599834825331, 51.63099561149414], [-0.928552267379979, 51.63092953870757], [-0.928477466267079, 51.630854225808044], [-0.928389580173335, 51.630782390113474], [-0.928294323595921, 51.6307167812279], [-0.928190294396403, 51.63065558801307], [-0.928078937075949, 51.630598823630024], [-0.927494137115659, 51.630339021667446], [-0.927177150281751, 51.63017967221046], [-0.927053070740772, 51.63011110151437], [-0.926922044883713, 51.63003077810591], [-0.926774152423019, 51.6299305188448], [-0.926569924361936, 51.62976860145066], [-0.926465515994788, 51.62966244509719], [-0.926222881099496, 51.62935271335746], [-0.925807083215573, 51.62885077488713], [-0.925685153671251, 51.62869140695483], [-0.925627779063265, 51.628612654944924], [-0.925107975398826, 51.62780494620014], [-0.925039238852947, 51.627717997425265], [-0.924853081975605, 51.627525670804864], [-0.924566287633664, 51.62725149768458], [-0.924018135317732, 51.62666651663998], [-0.9236755124427, 51.62631000590676], [-0.923506463123086, 51.62618886774415], [-0.92325024557972, 51.62602736696645], [-0.923179326155173, 51.62597186775246], [-0.923151247824846, 51.62593744208942], [-0.923025917353845, 51.62573937605691], [-0.922746731858051, 51.625388839233764], [-0.922647729925315, 51.625421200084226], [-0.922438316532782, 51.62517470633975], [-0.922266691774008, 51.62491866820555], [-0.922176577184834, 51.624819832363215], [-0.921722712186069, 51.62440384906751], [-0.921324388846087, 51.624082786314446], [-0.921078577970903, 51.623909687134365], [-0.920860652296657, 51.62377910436709], [-0.920574889783577, 51.623646099345635], [-0.920239048968319, 51.623492851580735], [-0.920014292502202, 51.62371107994427], [-0.919774493442185, 51.623954346092496], [-0.9196346398006, 51.62406455586703], [-0.919395541436808, 51.62427815528515], [-0.919291601043514, 51.624396787581134], [-0.919216417933559, 51.6245210794288], [-0.919153464283899, 51.62467785367513], [-0.919134125069682, 51.624762197061855], [-0.919115026043568, 51.62495803894169], [-0.919049238753011, 51.62517323267518], [-0.919009465019033, 51.625266379578875], [-0.918926652164549, 51.625407685106715], [-0.91889138185638, 51.62549368011671], [-0.918887531877765, 51.62553410703284], [-0.918896749679156, 51.62569334383204], [-0.918892707420934, 51.62574186144837], [-0.918872585162246, 51.62579832350382], [-0.918836276012485, 51.62586722482348], [-0.918763089019947, 51.62596815648993], [-0.918486277330256, 51.626309088016214], [-0.918317614737411, 51.62653682130949], [-0.917905561785174, 51.626975413689514], [-0.917718470441796, 51.62724883363936], [-0.917588198962995, 51.627380709193844], [-0.917518986462533, 51.627435819379606], [-0.917391270738013, 51.627520961779815], [-0.916852199941663, 51.62783249660931], [-0.916708494011591, 51.62822500463541], [-0.916564194300437, 51.62882431452802], [-0.91642514281193, 51.62950639562586], [-0.916399138398425, 51.62974892972319], [-0.916394191477189, 51.62995659074321], [-0.917260413231125, 51.62992321851857], [-0.917422640699178, 51.63166639247214], [-0.91745600722272, 51.63232848375385], [-0.917204699151121, 51.632324368705305], [-0.916787813832452, 51.632356490901394], [-0.916473041038736, 51.63240843616508], [-0.91615824611563, 51.63246127954521], [-0.916096846672852, 51.632491284427324], [-0.916000979824314, 51.632573122584574], [-0.916035541448316, 51.63300234215989], [-0.916058746179642, 51.633180590521675], [-0.916070697537387, 51.63322475979131], [-0.916098260729099, 51.63328076225654], [-0.916287121367376, 51.6334803208717], [-0.916556537933578, 51.63369500893812], [-0.916833436931067, 51.63389897542989], [-0.916980624704717, 51.63396776999687], [-0.917236275570907, 51.634093312450645], [-0.91746761535009, 51.63414759643489], [-0.917599467742121, 51.63382870989293], [-0.917652284973834, 51.63367364156546], [-0.917677934007693, 51.63362802065708], [-0.917745133700401, 51.63359716923921], [-0.917749446066394, 51.633598108140106], [-0.917778102484095, 51.633608262991594], [-0.918084580428658, 51.633662338963], [-0.918258883815884, 51.633684625273325], [-0.918506861448772, 51.63370758977881], [-0.918953829589691, 51.63374767133924], [-0.919245145699076, 51.633771033193085], [-0.919300707852053, 51.63386505735126], [-0.919518444759651, 51.63449197843591], [-0.919277685382965, 51.63446908250848], [-0.919031520477806, 51.63467362436313], [-0.918786199566619, 51.63490335001199], [-0.918632752044247, 51.63503681158531], [-0.918623327237537, 51.63512933850577], [-0.918590569006466, 51.635413172104], [-0.918679820058316, 51.63554886817429], [-0.918329488250497, 51.63557621368664], [-0.918276435808259, 51.635741170885815], [-0.918247752304029, 51.6360358318421], [-0.918226764712395, 51.6364321689642], [-0.918316733144818, 51.63702374696847], [-0.918287332378286, 51.63783452012518], [-0.918306713699577, 51.63835621240955], [-0.918316674296085, 51.639213205140855], [-0.918347519668651, 51.639799742499974], [-0.918322169732004, 51.63995416480466], [-0.918318885834364, 51.64003146244247], [-0.91832686087795, 51.64012145202931], [-0.91837911416845, 51.640354816042915], [-0.918418495846573, 51.64070405330022], [-0.918530296534871, 51.64128953760163], [-0.918512952473936, 51.64147190762244], [-0.918367217757134, 51.64200916315153], [-0.917905817511154, 51.6420255938785], [-0.917874522823857, 51.64200462484983], [-0.9178264462409, 51.64196012300076], [-0.917792775459127, 51.641917552189355], [-0.917773553228143, 51.64187511449974], [-0.917765526057023, 51.64184806570082], [-0.917757894232724, 51.6417436926823], [-0.917749532884981, 51.64142711089125], [-0.917739557627689, 51.64136048104305], [-0.917720785029217, 51.641299165096676], [-0.917688816437575, 51.64124581999865], [-0.917649452591449, 51.641199600032465], [-0.917568381483579, 51.64114490323613], [-0.917433423830488, 51.64098630616572], [-0.917315173490429, 51.64079369481265], [-0.916601390868836, 51.640243120219885], [-0.916329281834837, 51.640018517003504], [-0.916001068304932, 51.63966211774633], [-0.915790319174844, 51.63947044935813], [-0.915502073944432, 51.63913509831614], [-0.915393357554307, 51.63902799332443], [-0.915169439572157, 51.63884339546647], [-0.914312592230519, 51.638234837864296], [-0.913969150495335, 51.63797270396478], [-0.913808719070197, 51.63773204326735], [-0.913709021859032, 51.63761063348384], [-0.913238840648949, 51.637814889395024], [-0.912211197236081, 51.63818662075986], [-0.912057780107923, 51.6382571327065], [-0.911911629192503, 51.63832591344631], [-0.911683066608314, 51.6384568717294], [-0.911571655864317, 51.638583520328496], [-0.910821072629623, 51.63897039510019], [-0.910799442348496, 51.63890815232427], [-0.910457034748542, 51.63884473254883], [-0.90959863753988, 51.63872527019996], [-0.909397970101408, 51.639078576087414], [-0.909048252097236, 51.63925965643008], [-0.909362542404515, 51.63959166868019], [-0.90780907162756, 51.64013291512084], [-0.906217399025103, 51.640939038154336], [-0.905898125060113, 51.64111499768922], [-0.905490384709512, 51.641363863281036], [-0.905329841704473, 51.64154939281248], [-0.905189541321435, 51.641794455508446], [-0.90489098319803, 51.64194992468491], [-0.904781623731163, 51.641990266433346], [-0.904676706895303, 51.64202615370086], [-0.904609919053975, 51.64203901826923], [-0.904237228330216, 51.64209218907456], [-0.90337364044862, 51.64224597828853], [-0.902975191138407, 51.642348358507896], [-0.90292303291413, 51.6422939216028], [-0.902563354675933, 51.64240655335107], [-0.902346768622897, 51.642458479170756], [-0.900824166346957, 51.64291090498388], [-0.900831401206159, 51.64297031739377], [-0.900456613238591, 51.64299018760407], [-0.900019098619797, 51.64297440185565], [-0.899740380937974, 51.64290615240652], [-0.899740489711103, 51.64290165761423], [-0.899316872364163, 51.642849133775655], [-0.899203336991784, 51.642822893203494], [-0.898949902655656, 51.64272520647125], [-0.898783095909619, 51.642631028913314], [-0.898613530793898, 51.64253143027416], [-0.898274969154989, 51.64230885935864], [-0.898003026265053, 51.642080618381755], [-0.897815191816853, 51.641840577798526], [-0.897681652652772, 51.6416262230417], [-0.897327401428262, 51.64091885338664], [-0.896908641882592, 51.6401308512027], [-0.896689777704333, 51.63985994571793], [-0.896199107519928, 51.639356299928586], [-0.896147069948886, 51.63929736526477], [-0.896071667668875, 51.63912941223961], [-0.896034388155249, 51.63881974973283], [-0.89604243255033, 51.63866696761571], [-0.896079873457203, 51.63849378104931], [-0.896158355572289, 51.63829670279626], [-0.896345617779906, 51.63796397393339], [-0.896436991088377, 51.637771512438086], [-0.896627579786388, 51.63748017587825], [-0.896853716275347, 51.63721255114492], [-0.896930541034958, 51.63714313797598], [-0.897052325259386, 51.63706695367484], [-0.897622203318074, 51.636806151704704], [-0.897875248140837, 51.636679946210485], [-0.898045509693898, 51.63657094674504], [-0.898161794997489, 51.63648302058021], [-0.898300490282884, 51.636364732965696], [-0.898761753797595, 51.63587451909389], [-0.898944791614438, 51.635595696246455], [-0.899167964890093, 51.63497197055003], [-0.899296205851425, 51.63450920414348], [-0.899574174378538, 51.633591065468096], [-0.89965934952667, 51.63323579470252], [-0.899745200652967, 51.632733067337156], [-0.89977291429982, 51.632065248259224], [-0.899749317297925, 51.63190587518938], [-0.899730833669311, 51.631833768913715], [-0.899698165870897, 51.631750739777836], [-0.89965967663145, 51.63166945441679], [-0.899415121605884, 51.63126703489972], [-0.899342021743563, 51.6311233827535], [-0.899274678557411, 51.630980683675816], [-0.899221406706553, 51.63067446858268], [-0.899099405183406, 51.63046202142283], [-0.899036514315775, 51.63037421293725], [-0.898969246754073, 51.63028816171176], [-0.898790586842518, 51.63008867047265], [-0.898592010806669, 51.62987640386868], [-0.898497321924236, 51.62978919602221], [-0.898330098469121, 51.62965455114822], [-0.898092642525963, 51.62949676796704], [-0.897090362270362, 51.62894426419184], [-0.896737033461809, 51.62879887742956], [-0.896347312922056, 51.6286648367393], [-0.895633444660858, 51.62837398981453], [-0.895432402381131, 51.628264199314984], [-0.895328663542796, 51.62819308870188], [-0.895257753282041, 51.62813847178444], [-0.895144755729953, 51.62803220648194], [-0.894948239644532, 51.627795675481295], [-0.894944118635818, 51.62766795529761], [-0.894659948504904, 51.62723368184], [-0.894597856997988, 51.62711350846984], [-0.894557343909314, 51.62699713484451], [-0.894469809950127, 51.62655661915932], [-0.894297931114171, 51.625960652861906], [-0.894027819576293, 51.62530531541029], [-0.893931965007508, 51.62514795788166], [-0.893770350871199, 51.62496210671055], [-0.893637995566781, 51.62476124514902], [-0.893507481839104, 51.62466290563429], [-0.892108104715385, 51.62369479825078], [-0.891788795844237, 51.623459800649094], [-0.891922368328922, 51.62337294285213], [-0.891402229815371, 51.62296161084893], [-0.891224922435199, 51.622768414566416], [-0.890089770742591, 51.621276764770215], [-0.890188416566163, 51.62120036880181], [-0.889947380146256, 51.62101466068101], [-0.889727152716072, 51.62086421627997], [-0.889328903798693, 51.62066892786315], [-0.889153387824523, 51.620758083474584], [-0.888409981594066, 51.6201459098237], [-0.888016456293258, 51.619876030785385], [-0.887588982852847, 51.619754191291285], [-0.887143566599165, 51.61965735685454], [-0.88701981132148, 51.61963820065132], [-0.886790744842007, 51.619613550199404], [-0.886603228328527, 51.619602780759124], [-0.886388075513318, 51.619599841439666], [-0.886090409498186, 51.61960421155123], [-0.8851368584814, 51.61967159165818], [-0.883828125903616, 51.61979133688442], [-0.883515973065361, 51.619797361107345], [-0.883424375160774, 51.6198216668555], [-0.883259776293847, 51.619877648328995], [-0.883163867754863, 51.61990101371408], [-0.883044634749604, 51.619815357981636], [-0.881854770311083, 51.61956485587701], [-0.881704286246311, 51.61951666620604], [-0.881635675440863, 51.619487239450166], [-0.881560131370525, 51.619446057447796], [-0.881477720403852, 51.619390423316226], [-0.881374708667671, 51.619291432867335], [-0.880834298239682, 51.61853547912722], [-0.880617549323506, 51.618127888748454], [-0.880388345702594, 51.61816796449318], [-0.879226788544387, 51.6185884841998], [-0.878534686661489, 51.61883184500677], [-0.878385021629543, 51.61898507235025], [-0.878148819949825, 51.61913297697072], [-0.878102165244257, 51.61915051459153], [-0.87804120240859, 51.61916252048532], [-0.877967464227806, 51.619165412606506], [-0.877896924603018, 51.61915574690363], [-0.877839648002824, 51.61913541789456], [-0.877812586845032, 51.61911987344738], [-0.877382402665225, 51.61869944717381], [-0.877261875140598, 51.61866682400238], [-0.877087293116294, 51.618600414623565], [-0.876592344555959, 51.61846350297477], [-0.876408990128558, 51.61845995037962], [-0.876374465270622, 51.61845422502283], [-0.876347205240439, 51.61844677083749], [-0.87630299358364, 51.61842386858449], [-0.876241963569583, 51.618380124514495], [-0.876216636094276, 51.618352907107045], [-0.876152781748704, 51.618131100785114], [-0.876106882196741, 51.61811807314475], [-0.876305643178539, 51.617614643124426], [-0.875030363348109, 51.6174927341714], [-0.874705473526163, 51.61748872204597], [-0.874564111923802, 51.6174810731233], [-0.874279482039409, 51.61730930128958], [-0.874259717266618, 51.61699889890464], [-0.874416434195306, 51.61673604585861], [-0.874423036602998, 51.61652750219062], [-0.870144618410033, 51.61769939147719], [-0.870074692270606, 51.617607003497994], [-0.869665459226217, 51.61768399010514], [-0.869137937974611, 51.617812887107476], [-0.868711126950696, 51.61789959196275], [-0.868460959800069, 51.617969115035805], [-0.866874516019656, 51.61827841686334], [-0.866642434191741, 51.6183175388698], [-0.866517885416195, 51.61833072340073], [-0.866392071649004, 51.61833670224208], [-0.865776872894858, 51.61833166083683], [-0.865633662902087, 51.618340168339564], [-0.865493072065054, 51.618359490991885], [-0.864874419821269, 51.618492883413026], [-0.864829070270363, 51.61851582340227], [-0.8648101986804, 51.61846169086974], [-0.864778464993556, 51.618402038980314], [-0.864733824417545, 51.61833866562683], [-0.864681918741689, 51.61827702035103], [-0.864649512487616, 51.61824433697217], [-0.864492159027339, 51.61812502442397], [-0.864510219622979, 51.618037979732996], [-0.864490008258273, 51.61792179156664], [-0.863791866117017, 51.616668790850674], [-0.863578496430752, 51.61619016667409], [-0.863939572338851, 51.6160749702936], [-0.864141702322916, 51.61602027805823], [-0.864343742093738, 51.615969181278444], [-0.864684853799959, 51.61590144547291], [-0.864287415633653, 51.61573755014447], [-0.864114344880943, 51.615611790807684], [-0.86394143216696, 51.615479738556914], [-0.863424226660599, 51.6150224515856], [-0.863108525016747, 51.61470918210108], [-0.862999136822108, 51.61463618943345], [-0.862947760773663, 51.614611414387845], [-0.862827479233939, 51.614569786988696], [-0.862764327092327, 51.6145538895073], [-0.862690954996651, 51.614542388851355], [-0.862422671693898, 51.614528100870835], [-0.862278208948609, 51.61452939875511], [-0.862025067586916, 51.614544929155834], [-0.861633333855888, 51.61461576315295], [-0.861195617216796, 51.61467715820802], [-0.860991546767721, 51.61469406144679], [-0.860819513274215, 51.61470048511226], [-0.860591345418716, 51.61469917048917], [-0.860366335624517, 51.61468709604235], [-0.860199196800327, 51.61467108707321], [-0.860140174693704, 51.6146633207896], [-0.859842784619867, 51.61460018922178], [-0.85969929013584, 51.61456282905675], [-0.859501466379857, 51.61450336097874], [-0.859306643699259, 51.614439425872085], [-0.859175017225196, 51.614389591981386], [-0.858977780895874, 51.61430675031806], [-0.858172868778381, 51.61392127488393], [-0.856305510909038, 51.61299763777437], [-0.855879431428414, 51.61282624136621], [-0.855413827571698, 51.612676038205095], [-0.855073660630441, 51.61259179657028], [-0.854915624510577, 51.612558784566126], [-0.854688372582268, 51.61252150056368], [-0.854459541396129, 51.6124895957323], [-0.854208848612115, 51.61246556965946], [-0.853413812340721, 51.612436228916096], [-0.851724243907319, 51.61242871018406], [-0.851450292115, 51.612410744947404], [-0.850998615679464, 51.61233888823236], [-0.850653274334699, 51.61223120468302], [-0.850372939737194, 51.61235164666859], [-0.850315593337778, 51.61233490012849], [-0.850193999216673, 51.612288751000705], [-0.850146601119627, 51.612278395984944], [-0.849926028861458, 51.61226274823948], [-0.849854084982468, 51.61225215268858], [-0.849714847013531, 51.612218418620564], [-0.849473435162227, 51.61217019573735], [-0.849372523204365, 51.61216291272777], [-0.849235958321253, 51.61219484371945], [-0.849170915863905, 51.6121969037703], [-0.849112126238191, 51.61218014249445], [-0.8487984760956, 51.61201881385575], [-0.848813983178796, 51.61186251023449], [-0.848805967905994, 51.611779707971536], [-0.848777693193183, 51.61169850541887], [-0.848751669639592, 51.61164250170296], [-0.848740414389996, 51.61163070213332], [-0.848685616135578, 51.61162746733029], [-0.848598109857592, 51.61148993537107], [-0.848561752293423, 51.61144282198033], [-0.848420551583887, 51.61131555337684], [-0.848346143135118, 51.61123120073643], [-0.848017978126262, 51.61073074025961], [-0.84803240586268, 51.61067423405594], [-0.848009203184881, 51.61062095534751], [-0.848010806265629, 51.61061467688053], [-0.848360723390725, 51.61054078070849], [-0.848731046077576, 51.61040234328455], [-0.848814480324059, 51.61035820278237], [-0.848820437461021, 51.610351067821576], [-0.848690278305866, 51.610072847084595], [-0.847947554822518, 51.60900543974003], [-0.847435103308081, 51.6083125448088], [-0.847167998407497, 51.60796823756615], [-0.846186886755928, 51.60662333116728], [-0.845549998419521, 51.605828497430636], [-0.845383680959569, 51.60566770865375], [-0.844840468159951, 51.60522267062485], [-0.84443530295085, 51.60497141150611], [-0.844232696249957, 51.60481835643492], [-0.843486943931864, 51.60416181103064], [-0.84332558359401, 51.60420428093958], [-0.842908147301968, 51.603868373383044], [-0.842663709069561, 51.603714004109015], [-0.842310199280505, 51.603533382087996], [-0.841471682375652, 51.60311958453644], [-0.841215384127901, 51.602977683579475], [-0.840873068217364, 51.60281155440105], [-0.840467421086961, 51.602637605395635], [-0.840268344470896, 51.602516948405764], [-0.840203154295604, 51.60246864832527], [-0.838474883614574, 51.601841924417336], [-0.838334815858368, 51.60178568911777], [-0.838125139250388, 51.60168470536249], [-0.837520083534699, 51.60134782062488], [-0.837365310402971, 51.60124558073874], [-0.837143016970701, 51.6010734356079], [-0.83702163004049, 51.600964332538595], [-0.836879440722268, 51.60082175386177], [-0.836733036616179, 51.60067463738169], [-0.836105420124444, 51.59992210370809], [-0.836001567218505, 51.59980508080317], [-0.835894758960057, 51.59969072601903], [-0.835646409012494, 51.5994652683849], [-0.835572705263831, 51.59941148620318], [-0.835355212679077, 51.599278049641256], [-0.835001490423373, 51.59910819321327], [-0.834666328550124, 51.59894661249016], [-0.834023851532118, 51.59860753956394], [-0.833813699592692, 51.59846967713012], [-0.832219972267628, 51.59727861587006], [-0.831975375091702, 51.59713321406168], [-0.83180286996819, 51.597047874561696], [-0.83156138306724, 51.59695015903964], [-0.831279067386554, 51.596868221715724], [-0.831119729288761, 51.59683246683902], [-0.830996129682144, 51.596810555210986], [-0.830798964246538, 51.59678611250204], [-0.829935838169309, 51.596720865686486], [-0.82967342169104, 51.596707460026586], [-0.829378950815281, 51.59670542343618], [-0.828672101908656, 51.596738836236966], [-0.828529092462618, 51.59674190522934], [-0.828241907711544, 51.596737240965595], [-0.828066024571149, 51.59672739285258], [-0.827854311754233, 51.596707295846045], [-0.827399248313258, 51.59666228882735], [-0.827164974703315, 51.59662128423301], [-0.827063074447412, 51.59659778687348], [-0.826830893268571, 51.59653162563389], [-0.826403126611598, 51.596379885757386], [-0.826320361645679, 51.596342192238744], [-0.826196596762853, 51.596270819297594], [-0.825930135887572, 51.596078429107884], [-0.825702044863314, 51.59590980062742], [-0.825239717878873, 51.595531118786504], [-0.824901250965003, 51.59522021379687], [-0.824412039116432, 51.59470908081712], [-0.8242790371805, 51.59460434384618], [-0.824162427084317, 51.59453573788591], [-0.823734544991122, 51.59433363318264], [-0.822923577534385, 51.59387232098135], [-0.82274220720895, 51.593740122024236], [-0.822758790294358, 51.59343366962803], [-0.822450529949737, 51.592123177421634], [-0.822408018987733, 51.591980681321466], [-0.82236394886053, 51.59184266543808], [-0.822242174035691, 51.59158338051977], [-0.821801765862476, 51.5908065697487], [-0.821372709449585, 51.59009371260957], [-0.821171850754746, 51.58982284235581], [-0.820679968304875, 51.58936291919855], [-0.820417155492676, 51.58914357740762], [-0.82015811620844, 51.5888901042506], [-0.820045903377484, 51.58876399099103], [-0.81975498206002, 51.5884040936899], [-0.819793038416411, 51.58838379523831], [-0.819648800144719, 51.588268149727725], [-0.819147039514258, 51.58763368041164], [-0.818936357700162, 51.58740856531028], [-0.818746726401906, 51.58698404449756], [-0.818744261992127, 51.58691208559554], [-0.818786542624285, 51.586561832259704], [-0.818798419467402, 51.58638211648965], [-0.818772601288344, 51.58593047014409], [-0.818622316220491, 51.585380460186784], [-0.818493730937228, 51.58471737211902], [-0.818460174123387, 51.58461992329734], [-0.818316632401033, 51.58436670899539], [-0.818092592164715, 51.58404524580265], [-0.817774082795079, 51.58341531231479], [-0.817553796530972, 51.58311636524129], [-0.817445537064436, 51.58300557512581], [-0.81689125274485, 51.582562990062094], [-0.816348587477007, 51.58217357091916], [-0.816214612729635, 51.58210837837547], [-0.816144330954904, 51.58209148442308], [-0.816059129697027, 51.58209332267878], [-0.815742672724781, 51.5820523651453], [-0.815217212787465, 51.58194545592985], [-0.815002344756643, 51.58188304223224], [-0.814826435408141, 51.5818210214772], [-0.814485295861823, 51.581730356582035], [-0.81444044205173, 51.581790148477246], [-0.813566956536122, 51.581635656767844], [-0.813282023122958, 51.58154825394594], [-0.813052037332166, 51.581456910143594], [-0.812870182657061, 51.581346270732034], [-0.812790810356639, 51.58129061819263], [-0.812604263086127, 51.581138568732094], [-0.812386509085548, 51.58085492331321], [-0.812249092317067, 51.58070067277682], [-0.812167619564544, 51.58055957666617], [-0.812051961231651, 51.58029045130041], [-0.812042798783181, 51.580254391465495], [-0.812034433182585, 51.580187767648724], [-0.812033188044369, 51.58012481260171], [-0.812058064730261, 51.580000977815104], [-0.81229781440549, 51.579440518478464], [-0.812247901650195, 51.57941753400863], [-0.812446355706805, 51.57916777205078], [-0.81277233113049, 51.578787120404634], [-0.813191367818544, 51.57821318632392], [-0.813476583358647, 51.57767926033569], [-0.81372993476285, 51.57714950751218], [-0.813894821439398, 51.57669169369027], [-0.813998634879093, 51.57614064720803], [-0.814138744624452, 51.57508193151095], [-0.814120940539715, 51.57493428638376], [-0.81419874804071, 51.57321943977239], [-0.814492542549023, 51.572575897898666], [-0.814547744449169, 51.57211787423915], [-0.814549364628156, 51.57200009817749], [-0.81449843948966, 51.57157247390041], [-0.81447275908744, 51.57022974030085], [-0.814470739157426, 51.56964165674743], [-0.814429823166273, 51.56938407823071], [-0.814416473674158, 51.5693425811485], [-0.814362577800679, 51.569251219648685], [-0.81406844007837, 51.5689659058573], [-0.813908308238922, 51.56874308971205], [-0.813853532979604, 51.56863013877188], [-0.81375715260415, 51.56839717647337], [-0.81371284208748, 51.56815934527622], [-0.813667666933597, 51.567788426746645], [-0.813915408556528, 51.567527470860746], [-0.814280993234198, 51.56684059466537], [-0.814704823511867, 51.56613272518902], [-0.814994772052415, 51.56569055892733], [-0.815202529336662, 51.56519091397622], [-0.815219131565213, 51.56505170869626], [-0.815351636137841, 51.564671793906264], [-0.815511116853932, 51.56436408558186], [-0.815565592175225, 51.5642108755608], [-0.815662011458114, 51.564053592855515], [-0.815731002538058, 51.56389693250399], [-0.815762954470268, 51.56377766396064], [-0.815882314039101, 51.56307031436626], [-0.815899206541573, 51.563030920866616], [-0.815918960262566, 51.5629924554096], [-0.816100387305838, 51.56272812828101], [-0.816239061970809, 51.562387838558415], [-0.816351227865814, 51.56217946080997], [-0.816402225233145, 51.562104443964415], [-0.816445731089239, 51.56204014171416], [-0.816755073070336, 51.56173843863565], [-0.81682883069147, 51.5615089920632], [-0.81709149295673, 51.56100450196165], [-0.817126546068515, 51.5610435199925], [-0.817036868291134, 51.56144185218239], [-0.817602599672938, 51.56148891511105], [-0.817650902097453, 51.56129517879352], [-0.81772376875861, 51.56109989153342], [-0.818544773098936, 51.56114952106405], [-0.818940645385275, 51.56112652991029], [-0.819286252234888, 51.56087194248433], [-0.820505192935939, 51.560762809232635], [-0.821152924392013, 51.56109751750433], [-0.821401734784996, 51.56112699167495], [-0.821468077854438, 51.561127657861135], [-0.821837057068471, 51.56108460493917], [-0.822551882107614, 51.56083281445182], [-0.822991148836609, 51.56069335159132], [-0.823298868990794, 51.56056425765945], [-0.823427756279142, 51.560489119484224], [-0.823816316952276, 51.56018999039105], [-0.823841530161624, 51.56016326766115], [-0.823879440321637, 51.5600917131651], [-0.823939663402364, 51.55926686943448], [-0.824000930577316, 51.55924050793579], [-0.823876052668265, 51.55798579953388], [-0.823797968341331, 51.557154174451156], [-0.823813910366727, 51.55698348995032], [-0.824268965579194, 51.556733581409404], [-0.824612742777356, 51.55649154853787], [-0.826344281900068, 51.55484359477631], [-0.826657025878971, 51.55457337099326], [-0.827233265990788, 51.554040521447654], [-0.827929376968602, 51.55344502444081], [-0.828029419518581, 51.553368693973354], [-0.828246668974642, 51.55322159923911], [-0.828485269800709, 51.5530855074047], [-0.828605105979095, 51.55302466009866], [-0.829372820563392, 51.55267264797847], [-0.830416538296143, 51.552300003050114], [-0.830341853307235, 51.55217517181714], [-0.830015969895102, 51.55217192349864], [-0.82991663595149, 51.55216463892005], [-0.829524156953837, 51.55211486704629], [-0.829282415323888, 51.552092673855796], [-0.828838545910614, 51.55207835426137], [-0.828599504055965, 51.55206338004898], [-0.828680519991051, 51.55199764928292], [-0.828534433277995, 51.55195752639793], [-0.828384829125967, 51.55188589688778], [-0.827987906418731, 51.55167242458396], [-0.827957477145366, 51.551621766572], [-0.827834232346298, 51.55159086272802], [-0.827633977763617, 51.551525919798664], [-0.827259642164726, 51.55144395104261], [-0.826879262755715, 51.5513727108443], [-0.826619197529414, 51.551334143723224], [-0.825020961294276, 51.55117248609027], [-0.825087548806697, 51.55099511486544], [-0.825080332863119, 51.55093929339289], [-0.825041927300218, 51.55086247849746], [-0.82502361605882, 51.55078946149474], [-0.825044884876699, 51.55069166368164], [-0.825058487270179, 51.550667521970404], [-0.82509857658956, 51.550622964257876], [-0.825145597538488, 51.55058926609727], [-0.825325151596322, 51.5505056412203], [-0.824909915146001, 51.550164291306395], [-0.82525013660448, 51.550002248032946], [-0.825332063085088, 51.549957209837], [-0.825638185418255, 51.54977504214384], [-0.82578350044032, 51.54967668704559], [-0.825923116734683, 51.54957557721289], [-0.826170603160388, 51.54937393870707], [-0.826371785812396, 51.54917813090106], [-0.826492161334072, 51.549039961540565], [-0.826611394860751, 51.548890091280356], [-0.82670116630089, 51.54876420424681], [-0.826782355507479, 51.54863553380353], [-0.826823019292071, 51.54856850170786], [-0.827062757600335, 51.548106920435835], [-0.827101368877001, 51.54800749719491], [-0.827194201898492, 51.54770629998806], [-0.827307057244965, 51.54741159704493], [-0.827582602426052, 51.54684696658141], [-0.827901482950928, 51.54639156924703], [-0.828226190833503, 51.54604592938406], [-0.828636291311094, 51.545744301711125], [-0.82879259021163, 51.54566673370386], [-0.828904643767125, 51.545627388779295], [-0.829074413403866, 51.54558682127211], [-0.829642313890905, 51.54554213206049], [-0.831137752395514, 51.5457125947128], [-0.831296230672639, 51.545718668970665], [-0.831381409559054, 51.545715021306385], [-0.831520416985355, 51.54569302674314], [-0.831658465956176, 51.54565213966273], [-0.832162223002951, 51.54540897973132], [-0.832259763552867, 51.545373083913695], [-0.832342495362879, 51.54535232675641], [-0.832449690786029, 51.545333611293344], [-0.832560958333776, 51.54532482723805], [-0.832748224427793, 51.54533298427906], [-0.833594396864807, 51.5455158387706], [-0.833803468208608, 51.5455736658201], [-0.834066591719905, 51.54566080332341], [-0.834319302360527, 51.54576042533909], [-0.834632701147966, 51.545911902800114], [-0.834743597643834, 51.54597414830218], [-0.834972095381443, 51.546118487532766], [-0.835101437527799, 51.546192605160904], [-0.835308853525451, 51.54642845092972], [-0.835597379030446, 51.546650714213946], [-0.835675530378703, 51.54669644865621], [-0.835765285050956, 51.54673960061442], [-0.835946924814448, 51.54679895002405], [-0.836738145066418, 51.54693268079673], [-0.837616543696299, 51.54698454508781], [-0.837668585980954, 51.546979665457], [-0.837867989708348, 51.546964555807335], [-0.83797367625272, 51.54694851789646], [-0.838105566972017, 51.54692284834119], [-0.838233315283634, 51.54688994418392], [-0.838329229403341, 51.54686122067977], [-0.838482151664417, 51.546802489195365], [-0.839036827411148, 51.54642762424692], [-0.83955396219585, 51.54605418383688], [-0.840116011657223, 51.54567219327131], [-0.840736658187885, 51.54525391246058], [-0.840941426195899, 51.54514083988849], [-0.841049279937165, 51.54509604683764], [-0.841194847094701, 51.5450426342828], [-0.841299520083949, 51.545009498946165], [-0.841898633062652, 51.544870644649805], [-0.842282244574123, 51.54481328536381], [-0.842762474116396, 51.54475597844143], [-0.843565178344648, 51.54477737891959], [-0.844086979548171, 51.54484366398717], [-0.845732620874625, 51.545006428046236], [-0.847066038668597, 51.54519847249473], [-0.847735465249349, 51.545415455459946], [-0.84773690700669, 51.54541546961599], [-0.848634731053663, 51.54572550693968], [-0.849946581441456, 51.54620234699594], [-0.850255922443757, 51.54628810259981], [-0.850450510421732, 51.5463493547082], [-0.850677807173489, 51.54642891042725], [-0.850994850981171, 51.546552505063595], [-0.852786328510159, 51.547342426670774], [-0.85300310746802, 51.547496506935786], [-0.853571212311598, 51.54778799706584], [-0.854020445083318, 51.54798930492918], [-0.854581807452525, 51.548205193183556], [-0.85478620907829, 51.54827822314386], [-0.854963577157503, 51.54833660211785], [-0.855161244465997, 51.54839068294659], [-0.855663052553423, 51.5485088736389], [-0.856166529832507, 51.54867563412252], [-0.856279761006, 51.54870371304979], [-0.856530960852844, 51.54875111981111], [-0.856804082121709, 51.54878705024175], [-0.857112033920981, 51.54881432744164], [-0.857381573472553, 51.548820548731904], [-0.857549123049589, 51.54881049056259], [-0.857844479857821, 51.548764809719025], [-0.858057604662229, 51.54872012637499], [-0.858337617310588, 51.54865361386837], [-0.858552497890933, 51.54859635820055], [-0.859049392399301, 51.548450127924276], [-0.859439117962245, 51.5483792842905], [-0.859697682244768, 51.54836291412634], [-0.859779823131423, 51.54836551056866], [-0.860170027263243, 51.548390881318824], [-0.860456238387038, 51.54842243448379], [-0.861009536104037, 51.548500639150554], [-0.861158816462501, 51.54852906321894], [-0.861352413335375, 51.54857320311727], [-0.861544411683264, 51.54862362144007], [-0.861731905414109, 51.5486811891874], [-0.862073439754406, 51.548807688741114], [-0.86254414698236, 51.54901726458452], [-0.86282747298222, 51.54916477803516], [-0.863015068128655, 51.549276295417606], [-0.863120154717426, 51.549342054318615], [-0.863285809311142, 51.54946594721784], [-0.863418211576468, 51.54959311456195], [-0.863530092020445, 51.54973357070672], [-0.863653360363745, 51.549937978681236], [-0.863733641061499, 51.550131180181424], [-0.863790336700716, 51.5503448343906], [-0.863824973966162, 51.550691353426465], [-0.863841717303786, 51.55100353042492], [-0.863889686614544, 51.55116225019172], [-0.863971345177536, 51.55135816235228], [-0.864192531443895, 51.5518009005184], [-0.864636908176204, 51.552606367995786], [-0.864885616784935, 51.55304487507487], [-0.864984710926909, 51.55317801261536], [-0.865042267578469, 51.5532415116859], [-0.86524661818949, 51.553434113390985], [-0.866448255146234, 51.55464702695421], [-0.866553639357719, 51.55475954277147], [-0.86713929523259, 51.555454866418074], [-0.86728119491555, 51.55560729781788], [-0.867357192432134, 51.55568356216347], [-0.867846797612144, 51.55612348793147], [-0.867948777192819, 51.5561991033314], [-0.868039688780355, 51.55625572917072], [-0.868162193200772, 51.55631805467487], [-0.868334859667638, 51.55639345221028], [-0.868507816648064, 51.556457162985154], [-0.868686743286876, 51.556512838449954], [-0.868885971532242, 51.55656421341042], [-0.869870431325262, 51.55700170522159], [-0.870538382015661, 51.557289577406756], [-0.87065953954758, 51.55734829060127], [-0.870968323528286, 51.55751940747054], [-0.871084688448939, 51.55759695683154], [-0.871173919806704, 51.55766345498963], [-0.871421843971099, 51.55790412108149], [-0.871517352960249, 51.558008444760674], [-0.871560414081151, 51.55807539786269], [-0.871689483441928, 51.558339198343305], [-0.871715457861831, 51.558455441841], [-0.871819115572425, 51.558871857901316], [-0.872116688986198, 51.559438501590606], [-0.87224925001588, 51.559678057158926], [-0.872395481580982, 51.5598898694294], [-0.872503199025109, 51.56002578071336], [-0.872616797176149, 51.56015725249727], [-0.872767427555836, 51.560307962534345], [-0.873712440787397, 51.560887112412736], [-0.874019840047307, 51.56105730856152], [-0.874413245272104, 51.56124990894107], [-0.875159636577155, 51.56157807024888], [-0.875469862748955, 51.561692540724444], [-0.875618818634067, 51.561736229028845], [-0.87605776549836, 51.56183754414599], [-0.876366373823489, 51.56190074371407], [-0.87668521195865, 51.561958645316366], [-0.876968369886447, 51.56200091867397], [-0.877197163756339, 51.56202468778881], [-0.877516822654725, 51.5620493254706], [-0.878098847659676, 51.56208186543848], [-0.879220205739232, 51.56212315048378], [-0.879742407250114, 51.562124539056946], [-0.8803196812009, 51.56211566057546], [-0.88047709073344, 51.562109069498774], [-0.880781923890852, 51.5620912956137], [-0.881058065229737, 51.56206695318683], [-0.881262135404653, 51.56204012483733], [-0.881418631531618, 51.562011943580096], [-0.881649213834679, 51.56196288783239], [-0.882003250428868, 51.56187993977645], [-0.882376388095226, 51.56178278572967], [-0.882764299497775, 51.56167138432022], [-0.883194585739291, 51.561537905452155], [-0.883498576630078, 51.5614364931922], [-0.883756281221724, 51.56134003501421], [-0.884086956514705, 51.56120920221847], [-0.884407665982054, 51.56107287871968], [-0.885457870533961, 51.5606602434964], [-0.885606584631741, 51.56059601575753], [-0.88578613479336, 51.56050960117672], [-0.88595858283258, 51.56041862303493], [-0.886091760097573, 51.560340759581955], [-0.886521253482028, 51.56006159461465], [-0.886883345687433, 51.559824949307504], [-0.887389733197074, 51.559468282123994], [-0.887580604245187, 51.55927227271282], [-0.887708691217493, 51.559107139161064], [-0.888191015763102, 51.55861266662589], [-0.888192457957821, 51.55861268028735], [-0.888287760756616, 51.55849039596854], [-0.888562664893145, 51.558278995716826], [-0.888677108662246, 51.55814070717499], [-0.888887527216288, 51.55791161122132], [-0.889030158653071, 51.55774121885465], [-0.889203011709727, 51.557514464273005], [-0.88945350380216, 51.55717964382524], [-0.889600043815338, 51.556967026485395], [-0.889736358446423, 51.55670036168757], [-0.889858423154084, 51.55648571413559], [-0.889957478394766, 51.55626815130874], [-0.88999480235023, 51.556157006507235], [-0.890171676314085, 51.5555274577222], [-0.89040150985715, 51.554855248874496], [-0.891496918227321, 51.55316795557777], [-0.892148150167392, 51.55212836271704], [-0.892302414411729, 51.5517746441604], [-0.892679622502675, 51.55097074336506], [-0.892968782461996, 51.55046633574481], [-0.893655961353766, 51.54930928124159], [-0.894173495307085, 51.548604708475054], [-0.894625223197592, 51.54805597035748], [-0.895275002004698, 51.547308578527485], [-0.895581553072133, 51.54691762432374], [-0.89567259455686, 51.54679079793778], [-0.895853734572665, 51.54651645501248], [-0.896746527292651, 51.54508077321264], [-0.896901839906062, 51.544860136456265], [-0.897255891587921, 51.54494888564188], [-0.898115394177492, 51.545187148067974], [-0.89822539056202, 51.54523044209882], [-0.898280925208036, 51.54525973711452], [-0.898317695099433, 51.54528975512979], [-0.898473190139101, 51.54530020648797], [-0.899619101095523, 51.54544313546729], [-0.901006352145532, 51.54562517973134], [-0.901825064903737, 51.54570208025918], [-0.903152296119515, 51.54586195719927], [-0.903215411109321, 51.54587603470979], [-0.903297183099556, 51.545893883241035], [-0.903017403675823, 51.54655396139701], [-0.902616538461231, 51.54745118838641], [-0.902395351374664, 51.54801290343283], [-0.902224993241029, 51.54837997226972], [-0.902166365216381, 51.54859882282856], [-0.902146545476892, 51.54876318664974], [-0.902208891983797, 51.54892921824649], [-0.902230894835185, 51.549033728477525], [-0.902380735585514, 51.54999904656443], [-0.902673692529055, 51.551610411429984], [-0.902806620567669, 51.55250003963136], [-0.902816651036337, 51.55268266601908], [-0.902804979597758, 51.55292803179951], [-0.902756997764027, 51.55318384821566], [-0.902654701329301, 51.55353896524768], [-0.902427419928527, 51.55423280167036], [-0.901847751389036, 51.555843197130926], [-0.901770133963284, 51.556011515784924], [-0.90172081219273, 51.556082988265544], [-0.902203201151337, 51.55617741874876], [-0.906010818638152, 51.55679743475821], [-0.906204734572883, 51.556771367660915], [-0.906311884484255, 51.55675438267928], [-0.906358975073264, 51.55689599188705], [-0.90638590166065, 51.55691602462513], [-0.906615524939952, 51.55696492104195], [-0.907278267614382, 51.55705831304524], [-0.907858939004531, 51.55720578727805], [-0.908174621569804, 51.5572752632291], [-0.908339760107985, 51.55730647205926], [-0.908420198492941, 51.557320707807335], [-0.908923514869315, 51.557385632424236], [-0.909322889103033, 51.5574540848968], [-0.909506497855653, 51.557497152980005], [-0.909658336207082, 51.557541723987356], [-0.909754316957776, 51.55756959081508], [-0.909871264277585, 51.557625526703404], [-0.91002439519459, 51.55767640345812], [-0.91014009429463, 51.557724234915874], [-0.910363938659539, 51.55783421414451], [-0.910769828656022, 51.55805288423369], [-0.910899633150579, 51.55817457810929], [-0.911134211672749, 51.55843931338367], [-0.911191431662737, 51.558519870694006], [-0.911262279817118, 51.55863382382822], [-0.911345597527786, 51.558829717406], [-0.911347039740573, 51.55882973078292], [-0.911354152248679, 51.55895478193117], [-0.911501156990394, 51.55932300828838], [-0.911744284152759, 51.55977395051585], [-0.911784714781588, 51.55983277167005], [-0.911848028397377, 51.559899897522016], [-0.911951124589094, 51.55999256899618], [-0.912043240814804, 51.56006176008463], [-0.912343203354435, 51.560247072388215], [-0.91252735254784, 51.560389049785144], [-0.912663001694362, 51.56050809825428], [-0.913644040185922, 51.561715780647766], [-0.914729932802775, 51.56149024267299], [-0.915936249212879, 51.561720788632314], [-0.917099342153636, 51.56255696600573], [-0.917716153850379, 51.56209778262442], [-0.918510926061236, 51.561494569835055], [-0.919190082061234, 51.56187308324347], [-0.919265061021478, 51.56187467281339], [-0.919319677161742, 51.561883268238525], [-0.919395565855925, 51.56190734542486], [-0.919450182060758, 51.561915940789575], [-0.919451624375034, 51.56191595406745], [-0.919612764956992, 51.561873377936905], [-0.919684473323871, 51.562134798108005], [-0.919731696029427, 51.56227280618616], [-0.919795125391412, 51.562396576626476], [-0.919877773921036, 51.56250074208832], [-0.920024454979703, 51.56264236275641], [-0.920273793481437, 51.562835281288635], [-0.920455811890565, 51.56300779833283], [-0.92054707457537, 51.56311384087594], [-0.920622684574115, 51.56321074767881], [-0.920768557091237, 51.56344767224896], [-0.920815933327546, 51.56357938704838], [-0.92087756775181, 51.56365728255545], [-0.920897207761338, 51.56368084160506], [-0.920950783915168, 51.5637334861553], [-0.921113636188415, 51.563862665653886], [-0.921195103215065, 51.56395602921301], [-0.921351882125165, 51.56422002842434], [-0.921395592904906, 51.56432383493418], [-0.921420893006769, 51.56441308549212], [-0.921438619701684, 51.56451755238376], [-0.921413985191466, 51.56464410933019], [-0.92167481147157, 51.56453500840272], [-0.923479752756133, 51.56373602685831], [-0.924155377789785, 51.5634113259626], [-0.924873111301507, 51.56399247344971], [-0.924951149378637, 51.56404803772923], [-0.925274524870032, 51.56428388466152], [-0.92664770764064, 51.56515336065692], [-0.927393574791524, 51.56558368874587], [-0.927927453464337, 51.5659491340051], [-0.92835633038721, 51.56599441223158], [-0.928244524844939, 51.56725223174753], [-0.928125342518282, 51.56741209518939], [-0.9281054698832, 51.56745956981058], [-0.927839528670842, 51.568092855254655], [-0.93052584537502, 51.568532778436946], [-0.930434864440691, 51.56872077542371], [-0.930290537945866, 51.568968530677175], [-0.93032458943141, 51.568993118606556], [-0.930407160146686, 51.56904062792432], [-0.930494248489543, 51.56908008580425], [-0.93056005729139, 51.5691040638391], [-0.930644619283805, 51.56912821268005], [-0.930755210497826, 51.569149901051155], [-0.931002865082897, 51.56917193845677], [-0.931506345671459, 51.5692367670135], [-0.9319179887186, 51.56928007686346], [-0.93222706378822, 51.569328746497334], [-0.932389335623021, 51.56936169347699], [-0.932508352034028, 51.56939334769875], [-0.932608510110525, 51.56942932617174], [-0.932871163025979, 51.56955040480943], [-0.933086053531851, 51.569616199317096], [-0.933414865356232, 51.569684826955594], [-0.93386895042082, 51.56976448240679], [-0.934635570791928, 51.5700537823344], [-0.934785550106084, 51.57011898456062], [-0.934985327167408, 51.57021431104797], [-0.935122135234023, 51.5702874858722], [-0.935333952219633, 51.570423383659445], [-0.935683954424458, 51.570697207984594], [-0.935948857561102, 51.57084617434456], [-0.936321009353978, 51.57109861741231], [-0.936776166293208, 51.57138058458356], [-0.936874033955222, 51.57139136186155], [-0.937185388877335, 51.57140497135624], [-0.937358713203379, 51.57139754881963], [-0.937474500211682, 51.571382411871916], [-0.937604964789291, 51.57135661760672], [-0.938082770631526, 51.571224267138255], [-0.938303744516349, 51.57115343316592], [-0.938622419406116, 51.57103852370375], [-0.938583754985448, 51.57127375671787], [-0.938615426417796, 51.5714008261012], [-0.938651384040882, 51.57152973256723], [-0.938810396393867, 51.572013125409214], [-0.938917102284257, 51.5723881447753], [-0.938977920287056, 51.572564931845086], [-0.939147081147104, 51.57298457478389], [-0.93921529881351, 51.57340150695511], [-0.939295227462625, 51.57374930879435], [-0.939359853061118, 51.57401065198471]]]}}
benchmarks/parse.py view
@@ -2,6 +2,16 @@ import json, sys, time +def isint(x):+ try:+ int(x)+ return True+ except:+ return False++if len(sys.argv) > 2 and isint(sys.argv[1]) and isint(sys.argv[2]):+ sys.argv.pop(1)+ count = int(sys.argv[1]) for n in sys.argv[2:]:@@ -12,4 +22,4 @@ fp.seek(0) val = json.load(fp) end = time.time()- print ' ', end - start+ print ' %d good, %gs' % (count, end - start)
+ changelog view
@@ -0,0 +1,119 @@+0.7.0.0++ * The performance of encoding to and decoding of bytestrings+ have both improved by up to 2x, while also using less+ memory.++ * New dependency: the scientific package lets us parse+ floating point numbers more quickly and accurately.++ * eitherDecode, decodeStrictWith: fixed bugs.++ * Added FromJSON and ToJSON instances for Tree and Scientific.++ * Fixed the ToJSON instances for UTCTime and ZonedTime.++0.6 series++ * Much improved documentation.++ * Angle brackets are now escaped in JSON strings, to help avoid XSS+ attacks.++ * Fixed up handling of nullary constructors when using generic+ encoding.++ * Added ToJSON/FromJSON instances for:++ * The Fixed class+ * ISO-8601 dates: UTCTime, ZonedTime, and TimeZone++ * Added accessor functions for inspecting Values.++ * Added eitherDecode function that returns an error message if+ decoding fails.++0.5 to 0.6++ * This release introduces a slightly obscure, but+ backwards-incompatible, change.++ In the generic APIs of versions 0.4 and 0.5, fields whose+ names began with a "_" character would have this character+ removed. This no longer occurs, as it was both buggy and+ surprising (https://github.com/bos/aeson/issues/53).++ * Fixed a bug in generic decoding of nullary constructors+ (https://github.com/bos/aeson/issues/62).++0.4 to 0.5++ * When used with the UTF-8 encoding performance improvements+ introduced in version 0.11.1.12 of the text package, this+ release improves aeson's JSON encoding performance by 33%+ relative to aeson 0.4.++ As part of achieving this improvement, an API change was+ necessary. The fromValue function in the+ Data.Aeson.Encode module now uses the text package's+ Builder type instead of the blaze-builder package's+ Builder type.++0.3 to 0.4++ * The new decode function complements the longstanding+ encode function, and makes the API simpler.++ * New examples make it easier to learn to use the package+ (https://github.com/bos/aeson/tree/master/examples).++ * Generics support++ aeson's support for data-type generic programming makes it+ possible to use JSON encodings of most data types without+ writing any boilerplate instances.++ Thanks to Bas Van Dijk, aeson now supports the two major+ schemes for doing datatype-generic programming:++ * the modern mechanism, built into GHC itself+ (http://www.haskell.org/ghc/docs/latest/html/users_guide/generic-programming.html)++ * the older mechanism, based on SYB (aka "scrap your+ boilerplate")++ The modern GHC-based generic mechanism is fast and terse: in+ fact, its performance is generally comparable in performance+ to hand-written and TH-derived ToJSON and FromJSON+ instances. To see how to use GHC generics, refer to+ examples/Generic.hs.++ The SYB-based generics support lives in Data.Aeson.Generic+ and is provided mainly for users of GHC older than 7.2. SYB+ is far slower (by about 10x) than the more modern generic+ mechanism. To see how to use SYB generics, refer to+ examples/GenericSYB.hs.++ * We switched the intermediate representation of JSON objects+ from Data.Map to Data.HashMap which has improved type+ conversion performance.++ * Instances of ToJSON and FromJSON for tuples are between 45%+ and 70% faster than in 0.3.++ * Evaluation control++ This version of aeson makes explicit the decoupling between+ *identifying* an element of a JSON document and *converting*+ it to Haskell. See the Data.Aeson.Parser documentation for+ details.++ The normal aeson decode function performs identification+ strictly, but defers conversion until needed. This can+ result in improved performance (e.g. if the results of some+ conversions are never needed), but at a cost in increased+ memory consumption.++ The new decode' function performs identification and+ conversion immediately. This incurs an up-front cost in CPU+ cycles, but reduces reduce memory consumption.
− release-notes.markdown
@@ -1,113 +0,0 @@-# 0.6 series--Much improved documentation.--Angle brackets are now escaped in JSON strings, to help avoid XSS-attacks.--Fixed up handling of nullary constructors when using generic encoding.--Added ToJSON/FromJSON instances for:--* The `Fixed` class--* ISO-8601 dates: `UTCTime`, `ZonedTime`, and `TimeZone`--Added accessor functions for inspecting `Value`s.--Added `eitherDecode` function that returns an error message if-decoding fails.--# 0.5 to 0.6--This release introduces a slightly obscure, but-backwards-incompatible, change.--In the generic APIs of versions 0.4 and 0.5, fields whose names began-with a "`_`" character would have this character removed. This no-longer occurs, as [it was both buggy and-surprising](https://github.com/bos/aeson/issues/53).--Also:--* Fixed [a bug in generic decoding of nullary constructors](https://github.com/bos/aeson/issues/62)--# 0.4 to 0.5--When used with the UTF-8 encoding performance improvements introduced-in version 0.11.1.12 of the text package, this release improves-aeson's JSON encoding performance by 33% relative to aeson 0.4.--As part of achieving this improvement, an API change was necessary.-The `fromValue` function in the `Data.Aeson.Encode` module now uses-the text package's `Builder` type instead of the blaze-builder-package's `Builder` type.--# 0.3 to 0.4--## Ease of use--The new [`decode`-function](http://hackage.haskell.org/packages/archive/aeson/latest/doc/html/Data-Aeson.html#v:decode)-complements the longstanding `encode` function, and makes the API-simpler.--[New examples](https://github.com/bos/aeson/tree/master/examples) make-it easier to learn to use the package.---## Generics support--aeson's support for data-type generic programming makes it possible to-use JSON encodings of most data types without writing any boilerplate-instances.--Thanks to Bas Van Dijk, aeson now supports the two major schemes for-doing datatype-generic programming:--* the modern mechanism, [built into GHC- itself](http://www.haskell.org/ghc/docs/latest/html/users_guide/generic-programming.html)--* the older mechanism, based on SYB (aka "scrap your boilerplate")--The modern GHC-based generic mechanism is fast and terse: in fact, its-performance is generally comparable in performance to hand-written and-TH-derived `ToJSON` and `FromJSON` instances. To see how to use GHC-generics, refer to-[`examples/Generic.hs`](https://github.com/bos/aeson/blob/master/examples/Generic.hs).--The SYB-based generics support lives in-[Data.Aeson.Generic](http://hackage.haskell.org/packages/archive/aeson/latest/doc/html/Data-Aeson-Generic.html),-and is provided mainly for users of GHC older than 7.2. SYB is far-slower (by about 10x) than the more modern generic mechanism. To see-how to use SYB generics, refer to-[`examples/GenericSYB.hs`](https://github.com/bos/aeson/blob/master/examples/GenericSYB.hs).---## Improved performance--* We switched the intermediate representation of JSON objects from- `Data.Map` to- [`Data.HashMap`](http://hackage.haskell.org/package/unordered-containers),- which has improved type conversion performance.--* Instances of `ToJSON` and `FromJSON` for tuples are between 45% and- 70% faster than in 0.3.---## Evaluation control--This version of aeson makes explicit the decoupling between-*identifying* an element of a JSON document and *converting* it to-Haskell. See the-[`Data.Aeson.Parser`](http://hackage.haskell.org/packages/archive/aeson/latest/doc/html/Data-Aeson-Parser.html)-documentation for details.--The normal aeson `decode` function performs identification strictly,-but defers conversion until needed. This can result in improved-performance (e.g. if the results of some conversions are never-needed), but at a cost in increased memory consumption.--The new `decode'` function performs identification and conversion-immediately. This incurs an up-front cost in CPU cycles, but reduces-reduce memory consumption.
tests/Instances.hs view
@@ -40,7 +40,8 @@ arbitrary = ModifiedJulianDay `liftM` arbitrary instance Arbitrary DiffTime where- arbitrary = picosecondsToDiffTime `liftM` choose (0, 86400000000000000)+ arbitrary = (picosecondsToDiffTime . (* 1000000000)) <$>+ choose (0, 86400000) instance Arbitrary UTCTime where arbitrary = liftM2 UTCTime arbitrary arbitrary
tests/Properties.hs view
@@ -1,16 +1,21 @@ {-# LANGUAGE CPP, OverloadedStrings, RecordWildCards, ScopedTypeVariables #-} +import Control.Monad (forM)+import Data.Aeson (eitherDecode) import Data.Aeson.Encode import Data.Aeson.Parser (value) import Data.Aeson.Types-import Data.Attoparsec.Number import Test.Framework (Test, defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)+import Test.Framework.Providers.HUnit (testCase)+import Test.HUnit (assertFailure, assertEqual) import Test.QuickCheck (Arbitrary(..)) import qualified Data.Vector as V import qualified Data.Attoparsec.Lazy as L import qualified Data.ByteString.Lazy.Char8 as L import qualified Data.Text as T+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.Encoding as TLE import qualified Data.HashMap.Strict as H import Data.Time.Clock (UTCTime(..)) import Data.Time (ZonedTime(..))@@ -23,15 +28,22 @@ import qualified Data.Map as Map #endif +{-+roundTripCaml :: String -> Bool+roundTripCaml s = s == (camlFrom '_' $ camlTo '_' s)+ where+ camlFrom :: Char -> String -> String+ camlFrom c = concatMap capitalize $ split c+-} encodeDouble :: Double -> Double -> Bool encodeDouble num denom- | isInfinite d || isNaN d = encode (Number (D d)) == "null"- | otherwise = (read . L.unpack . encode . Number . D) d == d+ | isInfinite d || isNaN d = encode d == "null"+ | otherwise = (read . L.unpack . encode) d == d where d = num / denom encodeInteger :: Integer -> Bool-encodeInteger i = encode (Number (I i)) == L.pack (show i)+encodeInteger i = encode i == L.pack (show i) toParseJSON :: (Arbitrary a, Eq a) => (Value -> Parser a) -> (a -> Value) -> a -> Bool toParseJSON parsejson tojson x =@@ -62,7 +74,9 @@ result = parse parser () main :: IO ()-main = defaultMain tests+main = do+ comparisonTest <- encoderComparisonTests+ defaultMain (comparisonTest : tests) #ifdef GHC_GENERICS type P6 = Product6 Int Bool String (Approx Double) (Int, Approx Double) ()@@ -102,6 +116,10 @@ testProperty "encodeDouble" encodeDouble , testProperty "encodeInteger" encodeInteger ],+ -- testGroup "camlCase" [+ -- testProperty "camlTo" $ roundTripCaml "AnApiMethod"+ -- , testProperty "camlTo" $ roundTripCaml "anotherMethodType"+ -- ], testGroup "roundTrip" [ testProperty "Bool" $ roundTripEq True , testProperty "Double" $ roundTripEq (1 :: Approx Double)@@ -110,8 +128,8 @@ , testProperty "String" $ roundTripEq (""::String) , testProperty "Text" $ roundTripEq T.empty , testProperty "Foo" $ roundTripEq (undefined::Foo)- , testProperty "DotNetTime" $ roundTripEq (undefined :: Approx DotNetTime)- , testProperty "UTCTime" $ roundTripEq (undefined :: Approx UTCTime)+ , testProperty "DotNetTime" $ roundTripEq (undefined :: DotNetTime)+ , testProperty "UTCTime" $ roundTripEq (undefined :: UTCTime) , testProperty "ZonedTime" $ roundTripEq (undefined::ZonedTime) #ifdef GHC_GENERICS , testGroup "ghcGenerics" [@@ -198,3 +216,38 @@ ] #endif ]+++------------------------------------------------------------------------------+-- Comparison between bytestring and text encoders+------------------------------------------------------------------------------++encoderComparisonTests :: IO Test+encoderComparisonTests = do+ encoderTests <- forM testFiles $ \file0 -> do+ let file = "benchmarks/json-data/" ++ file0+ return $ testCase file $ do+ inp <- L.readFile file+ case eitherDecode inp of+ Left err -> assertFailure $ "Decoding failure: " ++ err+ Right val -> assertEqual "" (encode val) (encodeViaText val)+ return $ testGroup "Compare bytestring and text encoders" encoderTests+ where+ encodeViaText :: Value -> L.ByteString+ encodeViaText =+ TLE.encodeUtf8 . TLB.toLazyText . encodeToTextBuilder . toJSON++ testFiles =+ [ "example.json"+ , "integers.json"+ , "jp100.json"+ , "numbers.json"+ , "twitter10.json"+ , "twitter20.json"+ , "geometry.json"+ , "jp10.json"+ , "jp50.json"+ , "twitter1.json"+ , "twitter100.json"+ , "twitter50.json"+ ]