Hello community, here is the log from the commit of package ghc-aeson for openSUSE:Factory checked in at 2018-12-06 12:16:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-aeson (Old) and /work/SRC/openSUSE:Factory/.ghc-aeson.new.19453 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-aeson" Thu Dec 6 12:16:47 2018 rev:20 rq:653440 version:1.4.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-aeson/ghc-aeson.changes 2018-10-25 08:14:32.820117080 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-aeson.new.19453/ghc-aeson.changes 2018-12-06 12:16:47.605553528 +0100 @@ -1,0 +2,9 @@ +Sun Nov 25 03:01:12 UTC 2018 - [email protected] + +- Update aeson to version 1.4.2.0. + Upstream has edited the change log file since the last release in + a non-trivial way, i.e. they did more than just add a new entry + at the top. You can review the file at: + http://hackage.haskell.org/package/aeson-1.4.2.0/src/changelog.md + +------------------------------------------------------------------- Old: ---- aeson-1.4.1.0.tar.gz aeson.cabal New: ---- aeson-1.4.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-aeson.spec ++++++ --- /var/tmp/diff_new_pack.VsvAVH/_old 2018-12-06 12:16:48.085553012 +0100 +++ /var/tmp/diff_new_pack.VsvAVH/_new 2018-12-06 12:16:48.085553012 +0100 @@ -19,14 +19,13 @@ %global pkg_name aeson %bcond_with tests Name: ghc-%{pkg_name} -Version: 1.4.1.0 +Version: 1.4.2.0 Release: 0 Summary: Fast JSON parsing and encoding License: BSD-3-Clause Group: Development/Libraries/Haskell URL: https://hackage.haskell.org/package/%{pkg_name} Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz -Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal#/%{pkg_name}.cabal BuildRequires: ghc-Cabal-devel BuildRequires: ghc-attoparsec-devel BuildRequires: ghc-base-compat-devel @@ -83,7 +82,6 @@ %prep %setup -q -n %{pkg_name}-%{version} -cp -p %{SOURCE1} %{pkg_name}.cabal %build %ghc_lib_build ++++++ aeson-1.4.1.0.tar.gz -> aeson-1.4.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/Data/Aeson/Parser/Internal.hs new/aeson-1.4.2.0/Data/Aeson/Parser/Internal.hs --- old/aeson-1.4.1.0/Data/Aeson/Parser/Internal.hs 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/Data/Aeson/Parser/Internal.hs 1970-01-01 01:00:00.000000000 +0100 @@ -328,12 +328,11 @@ decimal0 :: Parser Integer decimal0 = do - let step a w = a * 10 + fromIntegral (w - zero) - zero = 48 + let zero = 48 digits <- A.takeWhile1 isDigit_w8 if B.length digits > 1 && B.unsafeHead digits == zero then fail "leading zero" - else return (B.foldl' step 0 digits) + else return (bsToInteger digits) -- | Parse a JSON number. scientific :: Parser Scientific @@ -366,3 +365,53 @@ fmap (Sci.scientific signedCoeff . (e +)) (signed decimal)) <|> return (Sci.scientific signedCoeff e) {-# INLINE scientific #-} + +------------------ Copy-pasted and adapted from base ------------------------ + +bsToInteger :: B.ByteString -> Integer +bsToInteger bs + | l > 40 = valInteger 10 l [ fromIntegral (w - 48) | w <- B.unpack bs ] + | otherwise = bsToIntegerSimple bs + where + l = B.length bs + +bsToIntegerSimple :: B.ByteString -> Integer +bsToIntegerSimple = B.foldl' step 0 where + step a b = a * 10 + fromIntegral (b - 48) -- 48 = '0' + +-- A sub-quadratic algorithm for Integer. Pairs of adjacent radix b +-- digits are combined into a single radix b^2 digit. This process is +-- repeated until we are left with a single digit. This algorithm +-- performs well only on large inputs, so we use the simple algorithm +-- for smaller inputs. +valInteger :: Integer -> Int -> [Integer] -> Integer +valInteger = go + where + go :: Integer -> Int -> [Integer] -> Integer + go _ _ [] = 0 + go _ _ [d] = d + go b l ds + | l > 40 = b' `seq` go b' l' (combine b ds') + | otherwise = valSimple b ds + where + -- ensure that we have an even number of digits + -- before we call combine: + ds' = if even l then ds else 0 : ds + b' = b * b + l' = (l + 1) `quot` 2 + + combine b (d1 : d2 : ds) = d `seq` (d : combine b ds) + where + d = d1 * b + d2 + combine _ [] = [] + combine _ [_] = errorWithoutStackTrace "this should not happen" + +-- The following algorithm is only linear for types whose Num operations +-- are in constant time. +valSimple :: Integer -> [Integer] -> Integer +valSimple base = go 0 + where + go r [] = r + go r (d : ds) = r' `seq` go r' ds + where + r' = r * base + fromIntegral d diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/Data/Aeson/QQ/Simple.hs new/aeson-1.4.2.0/Data/Aeson/QQ/Simple.hs --- old/aeson-1.4.1.0/Data/Aeson/QQ/Simple.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/aeson-1.4.2.0/Data/Aeson/QQ/Simple.hs 1970-01-01 01:00:00.000000000 +0100 @@ -0,0 +1,25 @@ +-- | Like "Data.Aeson.QQ" but without interpolation. +module Data.Aeson.QQ.Simple (aesonQQ) where + +import Data.Aeson +import qualified Data.Text as T +import qualified Data.Text.Encoding as TE +import Language.Haskell.TH +import Language.Haskell.TH.Quote +import Language.Haskell.TH.Syntax (Lift (..)) +import Prelude () +import Prelude.Compat + +aesonQQ :: QuasiQuoter +aesonQQ = QuasiQuoter + { quoteExp = aesonExp + , quotePat = const $ error "No quotePat defined for jsonQQ" + , quoteType = const $ error "No quoteType defined for jsonQQ" + , quoteDec = const $ error "No quoteDec defined for jsonQQ" + } + +aesonExp :: String -> ExpQ +aesonExp txt = + case eitherDecodeStrict $ TE.encodeUtf8 $ T.pack txt of + Left err -> error $ "Error in aesonExp: " ++ show err + Right val -> lift (val :: Value) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/Data/Aeson/Types/ToJSON.hs new/aeson-1.4.2.0/Data/Aeson/Types/ToJSON.hs --- old/aeson-1.4.1.0/Data/Aeson/Types/ToJSON.hs 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/Data/Aeson/Types/ToJSON.hs 1970-01-01 01:00:00.000000000 +0100 @@ -74,6 +74,7 @@ import Data.Fixed (Fixed, HasResolution) import Data.Foldable (toList) import Data.Functor.Compose (Compose(..)) +import Data.Functor.Contravariant (Contravariant (..)) import Data.Functor.Identity (Identity(..)) import Data.Functor.Product (Product(..)) import Data.Functor.Sum (Sum(..)) @@ -346,6 +347,13 @@ name .= value = (name, toJSON value) {-# INLINE (.=) #-} +-- | Constructs a singleton 'H.HashMap'. For calling functions that +-- demand an 'Object' for constructing objects. To be used in +-- conjunction with 'mconcat'. Prefer to use 'object' where possible. +instance KeyValue Object where + name .= value = H.singleton name (toJSON value) + {-# INLINE (.=) #-} + ------------------------------------------------------------------------------- -- Classes and types for map keys ------------------------------------------------------------------------------- @@ -498,6 +506,9 @@ . E.encodingToLazyByteString . e +instance Contravariant ToJSONKeyFunction where + contramap = contramapToJSONKeyFunction + -- | Contravariant map, as 'ToJSONKeyFunction' is a contravariant functor. contramapToJSONKeyFunction :: (b -> a) -> ToJSONKeyFunction a -> ToJSONKeyFunction b contramapToJSONKeyFunction h x = case x of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/aeson.cabal new/aeson-1.4.2.0/aeson.cabal --- old/aeson-1.4.1.0/aeson.cabal 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/aeson.cabal 1970-01-01 01:00:00.000000000 +0100 @@ -1,5 +1,5 @@ name: aeson -version: 1.4.1.0 +version: 1.4.2.0 license: BSD3 license-file: LICENSE category: Text, Web, JSON @@ -75,6 +75,7 @@ Data.Aeson.Text Data.Aeson.Types Data.Aeson.TH + Data.Aeson.QQ.Simple Data.Aeson.Encoding.Internal Data.Aeson.Internal @@ -99,26 +100,19 @@ Data.Attoparsec.Time Data.Attoparsec.Time.Internal + -- GHC bundled libs build-depends: - attoparsec >= 0.13.0.1, - base >= 4.5 && < 5, - base-compat >= 0.9.1 && < 0.11, - containers >= 0.4.2, - deepseq >= 1.3 && < 1.5, - dlist >= 0.6, - ghc-prim >= 0.2, - hashable >= 1.1.2.0, - primitive >= 0.6.1, - scientific >= 0.3.4.7 && < 0.4, - tagged >=0.8.3 && <0.9, - template-haskell >= 2.7, - text >= 1.2.3, - th-abstraction >= 0.2.2 && < 0.3, - time >= 1.1.1.4, - time-locale-compat >= 0.1.1 && < 0.2, - unordered-containers >= 0.2.5.0 && < 0.3, - uuid-types >= 1.0.3 && <1.1, - vector >= 0.8 + base >= 4.5.0.0 && < 5, + containers >= 0.4.2.1 && < 0.7, + deepseq >= 1.3.0.0 && < 1.5, + ghc-prim >= 0.2 && < 0.6, + template-haskell >= 2.7.0.0 && < 2.15, + text >= 1.2.3.0 && < 1.3, + time >= 1.4 && < 1.9 + + -- Compat + build-depends: + base-compat >= 0.9.1 && < 0.11 if flag(bytestring-builder) build-depends: bytestring >= 0.9.2 && < 0.10.4, @@ -126,19 +120,42 @@ else build-depends: bytestring >= 0.10.4 && < 0.11 + if !impl(ghc >= 8.6) + build-depends: + contravariant >=1.4.1 && <1.6 + if !impl(ghc >= 8.0) -- `Data.Semigroup` and `Control.Monad.Fail` and `Control.Monad.IO.Class` are available in base only since GHC 8.0 / base 4.9 build-depends: - semigroups >= 0.18.2 && < 0.19, - transformers >= 0.2.2.0, - transformers-compat >= 0.3, + semigroups >= 0.18.5 && < 0.19, + transformers >= 0.3.0.0 && < 0.6, + transformers-compat >= 0.6.2 && < 0.7, fail == 4.9.* if !impl(ghc >= 7.10) -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8 - build-depends: nats >= 1 && < 1.2, + build-depends: nats >= 1.1.1 && < 1.2, void >= 0.7.2 && < 0.8 + -- cannot use latest version + build-depends: + unordered-containers >= 0.2.8.0 && < 0.3, + + -- not in LTS-12.10 + tagged >= 0.8.5 && < 0.9, + primitive >= 0.6.3.0 && < 0.7 + + -- Other dependencies + build-depends: + attoparsec >= 0.13.2.2 && < 0.14, + dlist >= 0.8.0.4 && < 0.9, + hashable >= 1.2.7.0 && < 1.3, + scientific >= 0.3.6.2 && < 0.4, + th-abstraction >= 0.2.8.0 && < 0.3, + time-locale-compat >= 0.1.1.5 && < 0.2, + uuid-types >= 1.0.3 && < 1.1, + vector >= 0.12.0.1 && < 0.13 + ghc-options: -Wall if flag(developer) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/benchmarks/Compare/JsonBench.hs new/aeson-1.4.2.0/benchmarks/Compare/JsonBench.hs --- old/aeson-1.4.1.0/benchmarks/Compare/JsonBench.hs 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/benchmarks/Compare/JsonBench.hs 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE NoImplicitPrelude #-} @@ -21,7 +22,10 @@ import Typed.Common (load) import qualified Data.Aeson as Aeson import qualified Data.BufferBuilder.Json as Json + +#ifdef MIN_VERSION_json_builder import qualified Data.Json.Builder as JB +#endif data EyeColor = Green | Blue | Brown deriving (Eq, Show) @@ -268,6 +272,7 @@ <> "greeting"# Json..=# uGreeting <> "favoriteFruit"# Json..=# uFavouriteFruit +#ifdef MIN_VERSION_json_builder ---- json-builder instances ---- instance JB.Value EyeColor where @@ -319,6 +324,7 @@ <> t "friends" `JB.row` uFriends <> t "greeting" `JB.row` uGreeting <> t "favoriteFruit" `JB.row` uFavouriteFruit +#endif benchmarks :: Benchmark benchmarks = env (load "json-data/buffer-builder.json") $ @@ -326,5 +332,7 @@ bgroup "json-bench" [ bench "aeson" $ nf Aeson.encode parsedUserList , bench "buffer-builder" $ nf Json.encodeJson parsedUserList +#ifdef MIN_VERSION_json_builder , bench "json-builder" $ nf JB.toJsonLBS parsedUserList +#endif ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/benchmarks/Compare.hs new/aeson-1.4.2.0/benchmarks/Compare.hs --- old/aeson-1.4.1.0/benchmarks/Compare.hs 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/benchmarks/Compare.hs 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -6,16 +7,19 @@ import Prelude.Compat import Compare.BufferBuilder () -import Compare.JsonBuilder () import Criterion.Main import Data.BufferBuilder.Json -import Data.Json.Builder import Twitter import Twitter.Manual () import Typed.Common import qualified Data.Aeson as Aeson import qualified Compare.JsonBench as JsonBench +#ifdef MIN_VERSION_json_builder +import Data.Json.Builder +import Compare.JsonBuilder () +#endif + main :: IO () main = defaultMain [ @@ -23,7 +27,9 @@ bgroup "twitter" [ bench "aeson" $ nf Aeson.encode twtr , bench "buffer-builder" $ nf encodeJson twtr +#ifdef MIN_VERSION_json_builder , bench "json-builder" $ nf toJsonLBS twtr +#endif ] , JsonBench.benchmarks ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/benchmarks/Issue673.hs new/aeson-1.4.2.0/benchmarks/Issue673.hs --- old/aeson-1.4.1.0/benchmarks/Issue673.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/aeson-1.4.2.0/benchmarks/Issue673.hs 1970-01-01 01:00:00.000000000 +0100 @@ -0,0 +1,164 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} + +module Main ( + main, + input17, + input32, + input64, + input128, + input256, + input2048, + input4096, + input8192, + input16384, + ) where + +import Criterion.Main +import Prelude.Compat +import Data.Int (Int64) +import Data.Scientific (Scientific) +import Data.Aeson.Parser (scientific) + +import qualified Data.Attoparsec.ByteString.Lazy as AttoL +import qualified Data.Attoparsec.ByteString.Char8 as Atto8 +import qualified Data.Aeson as A +import qualified Data.ByteString as BS +import qualified Data.ByteString.Lazy as LBS +import qualified Data.ByteString.Lazy.Char8 as LBS8 + +decodeInt :: LBS.ByteString -> Maybe Int +decodeInt = A.decode + +decodeString :: LBS.ByteString -> Maybe String +decodeString = A.decode + +decodeScientific :: LBS.ByteString -> Maybe Scientific +decodeScientific = A.decode + +decodeViaRead :: LBS.ByteString -> Integer +decodeViaRead = read . LBS8.unpack + +decodeAtto :: LBS.ByteString -> Maybe Scientific +decodeAtto + = parseOnly (scientific <* AttoL.endOfInput) + where + parseOnly p lbs = case AttoL.parse p lbs of + AttoL.Done _ r -> Just r + AttoL.Fail {} -> Nothing + +decodeAtto8 :: LBS.ByteString -> Maybe Scientific +decodeAtto8 + = parseOnly (Atto8.scientific <* AttoL.endOfInput) + where + parseOnly p lbs = case AttoL.parse p lbs of + AttoL.Done _ r -> Just r + AttoL.Fail {} -> Nothing + +generate :: Int64 -> LBS.ByteString +generate n = LBS8.replicate n '1' + +input17 :: LBS.ByteString +input17 = generate 17 + +input32 :: LBS.ByteString +input32 = generate 32 + +input64 :: LBS.ByteString +input64 = generate 64 + +input128 :: LBS.ByteString +input128 = generate 128 + +input256 :: LBS.ByteString +input256 = generate 256 + +input2048 :: LBS.ByteString +input2048 = generate 2048 + +input4096 :: LBS.ByteString +input4096 = generate 4096 + +input8192 :: LBS.ByteString +input8192 = generate 8192 + +input16384 :: LBS.ByteString +input16384 = generate 16384 + + +main :: IO () +main = defaultMain + -- works on 64bit + [ benchPair "17" input17 + -- , benchPair "32" input32 + -- , benchPair "64" input64 + -- , benchPair "128" input128 + -- , benchPair "256" input256 + , benchPair "2048" input2048 + , benchPair "4096" input4096 + , benchPair "8192" input8192 + , benchPair "16384" input16384 + ] + where + benchPair name input = bgroup name + [ bench "Int" $ whnf decodeInt input + , bench "Simple" $ whnf bsToIntegerSimple (LBS.toStrict input) + , bench "Optim" $ whnf bsToInteger (LBS.toStrict input) + , bench "Read" $ whnf decodeViaRead input + , bench "Scientific" $ whnf decodeScientific input + , bench "parserA" $ whnf decodeAtto input + , bench "parserS" $ whnf decodeAtto8 input + , bench "String" $ whnf decodeString $ "\"" <> input <> "\"" + ] + +------------------------------------------------------------------------------- +-- better fromInteger +------------------------------------------------------------------------------- + +bsToInteger :: BS.ByteString -> Integer +bsToInteger bs + | l > 40 = valInteger 10 l [ fromIntegral (w - 48) | w <- BS.unpack bs ] + | otherwise = bsToIntegerSimple bs + where + l = BS.length bs + +bsToIntegerSimple :: BS.ByteString -> Integer +bsToIntegerSimple = BS.foldl' step 0 where + step a b = a * 10 + fromIntegral (b - 48) -- 48 = '0' + +-- A sub-quadratic algorithm for Integer. Pairs of adjacent radix b +-- digits are combined into a single radix b^2 digit. This process is +-- repeated until we are left with a single digit. This algorithm +-- performs well only on large inputs, so we use the simple algorithm +-- for smaller inputs. +valInteger :: Integer -> Int -> [Integer] -> Integer +valInteger = go + where + go :: Integer -> Int -> [Integer] -> Integer + go _ _ [] = 0 + go _ _ [d] = d + go b l ds + | l > 40 = b' `seq` go b' l' (combine b ds') + | otherwise = valSimple b ds + where + -- ensure that we have an even number of digits + -- before we call combine: + ds' = if even l then ds else 0 : ds + b' = b * b + l' = (l + 1) `quot` 2 + + combine b (d1 : d2 : ds) = d `seq` (d : combine b ds) + where + d = d1 * b + d2 + combine _ [] = [] + combine _ [_] = errorWithoutStackTrace "this should not happen" + +-- The following algorithm is only linear for types whose Num operations +-- are in constant time. +valSimple :: Integer -> [Integer] -> Integer +valSimple base = go 0 + where + go r [] = r + go r (d : ds) = r' `seq` go r' ds + where + r' = r * base + fromIntegral d diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/benchmarks/aeson-benchmarks.cabal new/aeson-1.4.2.0/benchmarks/aeson-benchmarks.cabal --- old/aeson-1.4.1.0/benchmarks/aeson-benchmarks.cabal 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/benchmarks/aeson-benchmarks.cabal 1970-01-01 01:00:00.000000000 +0100 @@ -63,6 +63,10 @@ -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9 build-depends: semigroups >= 0.18.2 && < 0.19 + if !impl(ghc >= 8.6) + build-depends: + contravariant >=1.4.1 && <1.6 + include-dirs: ../include ghc-options: -O2 -Wall @@ -155,7 +159,6 @@ other-modules: Compare.BufferBuilder Compare.JsonBench - Compare.JsonBuilder Twitter Twitter.Manual Typed.Common @@ -168,9 +171,14 @@ criterion >= 1.0, deepseq, ghc-prim, - json-builder, text + if impl(ghc < 8.4) + other-modules: + Compare.JsonBuilder + build-depends: + json-builder + executable aeson-benchmark-micro default-language: Haskell2010 main-is: Micro.hs @@ -318,3 +326,16 @@ text, unordered-containers, vector + +executable aeson-issue-673 + default-language: Haskell2010 + main-is: Issue673.hs + ghc-options: -Wall -O1 -rtsopts + build-depends: + aeson-benchmarks, + attoparsec, + base, + bytestring, + scientific, + base-compat, + criterion >= 1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/changelog.md new/aeson-1.4.2.0/changelog.md --- old/aeson-1.4.1.0/changelog.md 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/changelog.md 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,13 @@ For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/changelog.md](https://github.com/bos/aeson/blob/master/changelog.md). -#### 1.4.1.0 +### 1.4.2.0 + +* Add `Data.Aeson.QQ.Simple` which is a simpler version of the `aeson-qq` package, it does not support interpolation, thanks to Oleg Grenrus. +* Add `Contravariant ToJSONKeyFunction` instance, thanks to Oleg Grenrus. +* Add `KeyValue Object` instance, thanks to Robert Hensing +* Improved performance when parsing large numbers, thanks to Oleg Grenrus. + +### 1.4.1.0 * Optimizations of generics, thanks to Rémy Oudompheng, here are some numbers for GHC 8.4: * Compilation time: G/BigProduct.hs is 25% faster, G/BigRecord.hs is 2x faster. @@ -10,7 +17,7 @@ * Fixes handling of `UTCTime` wrt. leap seconds , thanks to Adam Schønemann * Warning and documentation fixes thanks to tom-bop, Gabor Greif, Ian Jeffries, and Mateusz Curyło. -### 1.4.0.0 +## 1.4.0.0 This release introduces bounds on the size of `Scientific` numbers when they are converted to other arbitrary precision types that do not represent them efficiently in memory. @@ -29,7 +36,7 @@ Finally, encoding integral values with large exponents now uses scientific notation, this saves space for large numbers. -### 1.3.1.1 +#### 1.3.1.1 * Catch 0 denominators when parsing Ratio diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-bench.yaml new/aeson-1.4.2.0/stack-bench.yaml --- old/aeson-1.4.1.0/stack-bench.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-bench.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +1,4 @@ -resolver: nightly-2018-03-12 +resolver: lts-12.10 # We use aeson in the snapshot to # - avoid recompilation of criterion # - compare against it @@ -9,5 +9,3 @@ work-dir: .stack-work-bench packages: - benchmarks -extra-deps: -- aeson-1.3.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-ffi-unescape.yaml new/aeson-1.4.2.0/stack-ffi-unescape.yaml --- old/aeson-1.4.1.0/stack-ffi-unescape.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-ffi-unescape.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +1,4 @@ -resolver: lts-10.0 +resolver: lts-12.10 packages: - '.' flags: @@ -6,4 +6,4 @@ fast: true cffi: true extra-deps: -- text-1.2.3.0 +- hashable-time-0.2.0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-lts10.yaml new/aeson-1.4.2.0/stack-lts10.yaml --- old/aeson-1.4.1.0/stack-lts10.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-lts10.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -resolver: lts-10.0 -packages: -- '.' -flags: - aeson: - fast: true - cffi: false - attoparsec-iso8601: - fast: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-lts12.yaml new/aeson-1.4.2.0/stack-lts12.yaml --- old/aeson-1.4.1.0/stack-lts12.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/aeson-1.4.2.0/stack-lts12.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -0,0 +1,10 @@ +resolver: lts-12.10 +packages: +- '.' +- attoparsec-iso8601 +flags: + aeson: + fast: true + cffi: true +extra-deps: +- hashable-time-0.2.0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-lts6.yaml new/aeson-1.4.2.0/stack-lts6.yaml --- old/aeson-1.4.1.0/stack-lts6.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-lts6.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,23 +0,0 @@ -resolver: lts-6.35 -packages: -- '.' -- attoparsec-iso8601 -extra-deps: -- semigroups-0.18.2 -- tagged-0.8.5 -- transformers-compat-0.5.1.4 -- QuickCheck-2.10.0.1 -- base-compat-0.9.3 -- hashable-1.2.6.1 -- integer-logarithms-1 -- quickcheck-instances-0.3.16 -- th-abstraction-0.2.2.0 -- text-1.2.3.0 -flags: -flags: - aeson: - fast: true - attoparsec-iso8601: - fast: true - semigroups: - bytestring-builder: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-lts7.yaml new/aeson-1.4.2.0/stack-lts7.yaml --- old/aeson-1.4.1.0/stack-lts7.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-lts7.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,17 +0,0 @@ -resolver: lts-7.24 -packages: -- '.' -- attoparsec-iso8601 -extra-deps: -- QuickCheck-2.10.0.1 -- base-compat-0.9.3 -- hashable-1.2.6.1 -- integer-logarithms-1 -- quickcheck-instances-0.3.16 -- th-abstraction-0.2.2.0 -- text-1.2.3.0 -flags: - aeson: - fast: true - attoparsec-iso8601: - fast: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-lts8.yaml new/aeson-1.4.2.0/stack-lts8.yaml --- old/aeson-1.4.1.0/stack-lts8.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-lts8.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,14 +0,0 @@ -resolver: lts-8.24 -packages: -- '.' -- attoparsec-iso8601 -extra-deps: -- QuickCheck-2.10.0.1 -- base-compat-0.9.3 -- quickcheck-instances-0.3.16 -- th-abstraction-0.2.2.0 -flags: - aeson: - fast: true - attoparsec-iso8601: - fast: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-lts9.yaml new/aeson-1.4.2.0/stack-lts9.yaml --- old/aeson-1.4.1.0/stack-lts9.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-lts9.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,12 +0,0 @@ -resolver: lts-9.9 -packages: -- '.' -- attoparsec-iso8601 -extra-deps: -- quickcheck-instances-0.3.16 -- QuickCheck-2.10.0.1 -flags: - aeson: - fast: true - attoparsec-iso8601: - fast: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/stack-nightly.yaml new/aeson-1.4.2.0/stack-nightly.yaml --- old/aeson-1.4.1.0/stack-nightly.yaml 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/stack-nightly.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +1,4 @@ -resolver: nightly-2018-03-07 +resolver: nightly-2018-09-26 packages: - '.' - attoparsec-iso8601 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aeson-1.4.1.0/tests/UnitTests.hs new/aeson-1.4.2.0/tests/UnitTests.hs --- old/aeson-1.4.1.0/tests/UnitTests.hs 2018-09-24 03:51:45.000000000 +0200 +++ new/aeson-1.4.2.0/tests/UnitTests.hs 1970-01-01 01:00:00.000000000 +0100 @@ -5,6 +5,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE QuasiQuotes #-} -- For Data.Aeson.Types.camelTo {-# OPTIONS_GHC -fno-warn-deprecations #-} @@ -25,9 +26,10 @@ import Control.Monad (forM, forM_) import Data.Aeson ((.=), (.:), (.:?), (.:!), FromJSON(..), FromJSONKeyFunction(..), FromJSONKey(..), ToJSON1(..), decode, eitherDecode, encode, fromJSON, genericParseJSON, genericToEncoding, genericToJSON, object, withObject, withEmbeddedJSON) import Data.Aeson.Internal (JSONPathElement(..), formatError) +import Data.Aeson.QQ.Simple (aesonQQ) import Data.Aeson.TH (deriveJSON, deriveToJSON, deriveToJSON1) import Data.Aeson.Text (encodeToTextBuilder) -import Data.Aeson.Types (Options(..), Result(Success), ToJSON(..), Value(Null), camelTo, camelTo2, defaultOptions, omitNothingFields, parse) +import Data.Aeson.Types (Options(..), Result(Success), ToJSON(..), Value(Null, Object), camelTo, camelTo2, defaultOptions, omitNothingFields, parse) import Data.Char (toUpper) import Data.Either.Compat (isLeft, isRight) import Data.Hashable (hash) @@ -93,6 +95,7 @@ , testGroup ".:, .:?, .:!" $ fmap (testCase "-") dotColonMark , testGroup "JSONPath" $ fmap (testCase "-") jsonPath , testGroup "Hashable laws" $ fmap (testCase "-") hashableLaws + , testGroup "Object construction" $ fmap (testCase "-") objectConstruction , testGroup "Issue #351" $ fmap (testCase "-") issue351 , testGroup "Nullary constructors" $ fmap (testCase "-") nullaryConstructors , testGroup "FromJSONKey" $ fmap (testCase "-") fromJSONKeyAssertions @@ -107,6 +110,10 @@ , testCase "Big integer decoding" bigIntegerDecoding , testCase "Big natural decading" bigNaturalDecoding , testCase "Big integer key decoding" bigIntegerKeyDecoding + , testGroup "QQ.Simple" + [ testCase "example" $ + assertEqual "" (object ["foo" .= True]) [aesonQQ| {"foo": true } |] + ] ] roundTripCamel :: String -> Assertion @@ -302,6 +309,18 @@ a = object ["223" .= False, "807882556" .= True] b = object ["807882556" .= True, "223" .= False] +------------------------------------------------------------------------------ +-- Check that an alternative way to construct objects works +------------------------------------------------------------------------------ + +objectConstruction :: [Assertion] +objectConstruction = [ + assertEqual "Equal objects constructed differently" recommended notRecommended + ] + where + recommended = object ["foo" .= True, "bar" .= (-1 :: Int)] + notRecommended = Object (mconcat ["foo" .= True, "bar" .= (-1 :: Int)]) + ------------------------------------------------------------------------------- -- ToJSONKey -------------------------------------------------------------------------------
