diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2016-2018, Renzo Carbonara
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Renzo Carbonara nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+This library exports `FromJSON` and `ToJSON` instances (from the
+`aeson` library) for many of the types exported by the `safe-money`
+library.
+
+Note: The code in this library used to be part of the `safe-money`
+library itself, so these instances are intended to be backwards
+compatible with older versions of `safe-money`.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+#! /usr/bin/env nix-shell
+#! nix-shell ./shell.nix -i runghc
+import Distribution.Simple
+main = defaultMain
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,4 @@
+# Version 0.1
+
+* This first release of @safe-money-aeson@ includes the same @aeson@ support
+  and tests that were present in @safe-money-0.6@.
diff --git a/safe-money-aeson.cabal b/safe-money-aeson.cabal
new file mode 100644
--- /dev/null
+++ b/safe-money-aeson.cabal
@@ -0,0 +1,56 @@
+name: safe-money-aeson
+version: 0.1
+license: BSD3
+license-file: LICENSE
+copyright: Copyright (c) Renzo Carbonara 2016-2018
+author: Renzo Carbonara
+maintainer: renλren!zone
+stability: Experimental
+tested-with: GHC==8.4.1
+homepage: https://github.com/k0001/safe-money
+bug-reports: https://github.com/k0001/safe-money/issues
+category: Money
+build-type: Simple
+cabal-version: >=1.10
+extra-source-files: README.md changelog.md
+synopsis: Instances from the aeson library for the safe-money library.
+description:
+  This library exports @FromJSON@ and @ToJSON@ instances (from the
+  @aeson@ library) for many of the types exported by the @safe-money@
+  library.
+  .
+  Note: The code in this library used to be part of the @safe-money@
+  library itself, so these instances are intended to be backwards
+  compatible with older versions of @safe-money@.
+
+source-repository head
+  type: git
+  location: https://github.com/k0001/safe-money
+
+library
+  default-language: Haskell2010
+  hs-source-dirs: src
+  ghc-options: -Wall -O2
+  build-depends:
+    aeson,
+    base >=4.8 && <5.0,
+    safe-money >=0.7,
+    text
+  exposed-modules:
+    Money.Aeson
+
+test-suite test
+  default-language: Haskell2010
+  type: exitcode-stdio-1.0
+  hs-source-dirs: test
+  main-is: Main.hs
+  build-depends:
+    aeson,
+    base,
+    bytestring,
+    safe-money,
+    safe-money-aeson,
+    tasty,
+    tasty-hunit,
+    tasty-quickcheck,
+    text
diff --git a/src/Money/Aeson.hs b/src/Money/Aeson.hs
new file mode 100644
--- /dev/null
+++ b/src/Money/Aeson.hs
@@ -0,0 +1,166 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+-- | This module only exports orphan 'Ae.FromJSON' and 'Ae.ToJSON' instances.
+-- Import as:
+--
+-- @
+-- import "Money.Aeson" ()
+-- @
+module Money.Aeson () where
+
+import Control.Applicative ((<|>), empty)
+import Control.Monad ((<=<), when)
+import qualified Data.Aeson as Ae
+import Data.Ratio ((%), numerator, denominator)
+import qualified Data.Text as T
+import GHC.TypeLits (KnownSymbol)
+import qualified Money
+import qualified Money.Internal as MoneyI
+
+--------------------------------------------------------------------------------
+-- | Compatible with 'Money.SomeDense'
+--
+-- Example rendering @'Money.dense'' (2 '%' 3) :: 'Money.Dense' \"BTC\"@:
+--
+-- @
+-- [\"BTC\", 2, 3]
+-- @
+--
+-- Note: The JSON serialization changed in version 0.4 (the leading @"Dense"@
+-- string was dropped from the rendered 'Ae.Array').
+instance KnownSymbol currency => Ae.ToJSON (Money.Dense currency) where
+  toJSON = Ae.toJSON . Money.toSomeDense
+
+-- | Compatible with 'Money.SomeDense'
+--
+-- Note: The JSON serialization changed in @safe-money@ version 0.4. However,
+-- this instance is still able to cope with the previous format.
+instance KnownSymbol currency => Ae.FromJSON (Money.Dense currency) where
+  parseJSON = maybe empty pure <=< fmap Money.fromSomeDense . Ae.parseJSON
+
+-- | Compatible with 'Money.Dense'
+--
+-- Note: The JSON serialization changed in @safe-money@ version 0.4 (the leading
+-- @"Dense"@ string was dropped from the rendered 'Ae.Array').
+instance Ae.ToJSON Money.SomeDense where
+  toJSON = \sd ->
+    let r = Money.someDenseAmount sd
+    in Ae.toJSON (MoneyI.someDenseCurrency' sd, numerator r, denominator r)
+
+-- | Compatible with 'Money.Dense'.
+--
+-- Note: The JSON serialization changed in @safe-money@ version 0.4. However,
+-- this instance is still able to cope with the previous format.
+instance Ae.FromJSON Money.SomeDense where
+  parseJSON = \v -> do
+    (c, n, d) <- Ae.parseJSON v <|> do
+       -- Pre 0.4 format.
+       ("Dense" :: String, c, n, d) <- Ae.parseJSON v
+       pure (c, n, d)
+    when (d == 0) (fail "denominator is zero")
+    maybe empty pure (MoneyI.mkSomeDense' c (n % d))
+
+-- | Compatible with 'Money.SomeDiscrete'
+--
+-- Example rendering @'Money.discrete' 43 :: 'Money.Discrete' \"BTC\" \"satoshi\"@:
+--
+-- @
+-- [\"BTC\", 100000000, 1, 43]
+-- @
+--
+-- Note: The JSON serialization changed in @safe-money@ version 0.4 (the leading
+-- @"Discrete"@ string was dropped from the rendered 'Ae.Array').
+instance
+  ( KnownSymbol currency, Money.GoodScale scale
+  ) => Ae.ToJSON (Money.Discrete' currency scale) where
+  toJSON = Ae.toJSON . Money.toSomeDiscrete
+
+-- | Compatible with 'Money.SomeDiscrete'
+--
+-- Note: The JSON serialization changed in @safe-money@ version 0.4. However,
+-- this instance is still able to cope with the previous format.
+instance
+  ( KnownSymbol currency, Money.GoodScale scale
+  ) => Ae.FromJSON (Money.Discrete' currency scale) where
+  parseJSON = maybe empty pure <=< fmap Money.fromSomeDiscrete . Ae.parseJSON
+
+-- | Compatible with 'Money.Discrete''
+--
+-- Note: The JSON serialization changed in version 0.4 (the leading @"Discrete"@
+-- string was dropped from the rendered 'Ae.Array').
+instance Ae.ToJSON Money.SomeDiscrete where
+  toJSON = \sd ->
+    let r = Money.someDiscreteScale sd
+    in Ae.toJSON (MoneyI.someDiscreteCurrency' sd,
+                  numerator r, denominator r,
+                  Money.someDiscreteAmount sd)
+
+-- | Compatible with 'Money.Discrete''
+--
+-- Note: The JSON serialization changed in version 0.4. However, this instance
+-- is still able to cope with the previous format.
+instance Ae.FromJSON Money.SomeDiscrete where
+  parseJSON = \v -> do
+    (c, n, d, a) <- Ae.parseJSON v <|> do
+       -- Pre 0.4 format.
+       ("Discrete" :: T.Text, c, n, d, a) <- Ae.parseJSON v
+       pure (c, n, d, a)
+    when (d == 0) (fail "denominator is zero")
+    maybe empty pure (MoneyI.mkSomeDiscrete' c (n % d) a)
+
+-- | Compatible with 'Money.SomeExchangeRate'
+--
+-- Example rendering an 'Money.ExchangeRate' constructed with
+-- @'Money.exchangeRate' (5 '%' 7) :: 'Money.ExchangeRate' \"USD\" \"JPY\"@
+--
+-- @
+-- [\"USD\", \"JPY\", 5, 7]
+-- @
+--
+-- Note: The JSON serialization changed in version 0.4 (the leading
+-- @"ExchangeRate"@ string was dropped from the rendered 'Ae.Array').
+instance
+  ( KnownSymbol src, KnownSymbol dst
+  ) => Ae.ToJSON (Money.ExchangeRate src dst) where
+  toJSON = Ae.toJSON . Money.toSomeExchangeRate
+
+-- | Compatible with 'Money.SomeExchangeRate'
+--
+-- Note: The JSON serialization changed in version 0.4. However, this instance
+-- is still able to cope with the previous format.
+instance
+  ( KnownSymbol src, KnownSymbol dst
+  ) => Ae.FromJSON (Money.ExchangeRate src dst) where
+  parseJSON =
+    maybe empty pure <=< fmap Money.fromSomeExchangeRate . Ae.parseJSON
+
+-- | Compatible with 'Money.ExchangeRate'
+--
+-- Note: The JSON serialization changed in @safe-money@ version 0.4 (the leading
+-- @"ExchangeRate"@ string was dropped from the rendered 'Ae.Array').
+instance Ae.ToJSON Money.SomeExchangeRate where
+  toJSON = \ser ->
+    let r = Money.someExchangeRateRate ser
+    in Ae.toJSON (MoneyI.someExchangeRateSrcCurrency' ser,
+                  MoneyI.someExchangeRateDstCurrency' ser,
+                  numerator r, denominator r)
+
+-- | Compatible with 'Money.ExchangeRate'
+--
+-- Note: The JSON serialization changed in @safe-money@ version 0.4. However,
+-- this instance is still able to cope with the previous format.
+instance Ae.FromJSON Money.SomeExchangeRate where
+  parseJSON = \v -> do
+    (src, dst, n, d) <- Ae.parseJSON v <|> do
+       -- Pre 0.4 format.
+       ("ExchangeRate" :: T.Text, src, dst, n, d) <- Ae.parseJSON v
+       pure (src, dst, n, d)
+    when (d == 0) (fail "denominator is zero")
+    maybe empty pure (MoneyI.mkSomeExchangeRate' src dst (n % d))
+
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,240 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeApplications #-}
+
+module Main where
+
+import qualified Data.Aeson as Ae
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Char as Char
+import Data.Proxy (Proxy(Proxy))
+import Data.Ratio ((%), numerator, denominator)
+import qualified Data.Text as T
+import Data.Word (Word8)
+import GHC.Exts (fromList)
+import GHC.TypeLits (Nat, Symbol, KnownSymbol, symbolVal)
+import qualified Money
+import qualified Test.Tasty as Tasty
+import Test.Tasty.HUnit ((@?=), (@=?))
+import qualified Test.Tasty.HUnit as HU
+import qualified Test.Tasty.Runners as Tasty
+import Test.Tasty.QuickCheck ((===), (==>), (.&&.))
+import qualified Test.Tasty.QuickCheck as QC
+
+import qualified Money.Aeson
+
+--------------------------------------------------------------------------------
+
+main :: IO ()
+main =  Tasty.defaultMainWithIngredients
+  [ Tasty.consoleTestReporter
+  , Tasty.listingTests
+  ] (Tasty.localOption (QC.QuickCheckTests 100) tests)
+
+tests :: Tasty.TestTree
+tests =
+  Tasty.testGroup "root"
+  [ testCurrencies
+  , testCurrencyUnits
+  , testExchange
+  , testRawSerializations
+  ]
+
+testCurrencies :: Tasty.TestTree
+testCurrencies =
+  Tasty.testGroup "Currency"
+  [ testDense (Proxy :: Proxy "BTC")  -- A cryptocurrency.
+  , testDense (Proxy :: Proxy "USD")  -- A fiat currency with decimal fractions.
+  , testDense (Proxy :: Proxy "VUV")  -- A fiat currency with non-decimal fractions.
+  , testDense (Proxy :: Proxy "XAU")  -- A precious metal.
+  ]
+
+testCurrencyUnits :: Tasty.TestTree
+testCurrencyUnits =
+  Tasty.testGroup "Currency units"
+  [ testDiscrete (Proxy :: Proxy "BTC") (Proxy :: Proxy "BTC")
+  , testDiscrete (Proxy :: Proxy "BTC") (Proxy :: Proxy "satoshi")
+  , testDiscrete (Proxy :: Proxy "BTC") (Proxy :: Proxy "bitcoin")
+  , testDiscrete (Proxy :: Proxy "USD") (Proxy :: Proxy "USD")
+  , testDiscrete (Proxy :: Proxy "USD") (Proxy :: Proxy "cent")
+  , testDiscrete (Proxy :: Proxy "USD") (Proxy :: Proxy "dollar")
+  , testDiscrete (Proxy :: Proxy "VUV") (Proxy :: Proxy "vatu")
+  , testDiscrete (Proxy :: Proxy "XAU") (Proxy :: Proxy "gram")
+  , testDiscrete (Proxy :: Proxy "XAU") (Proxy :: Proxy "grain")
+  ]
+
+testDense
+  :: forall currency
+  .  KnownSymbol currency
+  => Proxy currency
+  -> Tasty.TestTree
+testDense pc =
+  Tasty.testGroup ("Dense " ++ show (symbolVal pc))
+  [ QC.testProperty "Aeson encoding roundtrip" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Dense currency) ->
+         Just x === Ae.decode (Ae.encode x)
+  , QC.testProperty "Aeson encoding roundtrip (SomeDense)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Dense currency) ->
+         let x' = Money.toSomeDense x
+         in Just x' === Ae.decode (Ae.encode x')
+  , QC.testProperty "Aeson encoding roundtrip (Dense through SomeDense)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Dense currency) ->
+         Just x === Ae.decode (Ae.encode (Money.toSomeDense x))
+  , QC.testProperty "Aeson encoding roundtrip (SomeDense through Dense)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Dense currency) ->
+         Just (Money.toSomeDense x) === Ae.decode (Ae.encode x)
+  , QC.testProperty "Aeson decoding of pre-0.4 format (Dense, SomeDense)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Dense currency) ->
+        let sx = Money.toSomeDense x
+            c = T.unpack (Money.someDenseCurrency sx)
+            r = Money.someDenseAmount sx
+            bs = Ae.encode ("Dense" :: String, c, numerator r, denominator r)
+        in (Just  x === Ae.decode bs) .&&.
+           (Just sx === Ae.decode bs)
+  ]
+
+testExchange :: Tasty.TestTree
+testExchange =
+  Tasty.testGroup "Exchange"
+  [ testExchangeRate (Proxy :: Proxy "BTC") (Proxy :: Proxy "BTC")
+  , testExchangeRate (Proxy :: Proxy "BTC") (Proxy :: Proxy "USD")
+  , testExchangeRate (Proxy :: Proxy "BTC") (Proxy :: Proxy "VUV")
+  , testExchangeRate (Proxy :: Proxy "BTC") (Proxy :: Proxy "XAU")
+  , testExchangeRate (Proxy :: Proxy "USD") (Proxy :: Proxy "BTC")
+  , testExchangeRate (Proxy :: Proxy "USD") (Proxy :: Proxy "USD")
+  , testExchangeRate (Proxy :: Proxy "USD") (Proxy :: Proxy "VUV")
+  , testExchangeRate (Proxy :: Proxy "USD") (Proxy :: Proxy "XAU")
+  , testExchangeRate (Proxy :: Proxy "VUV") (Proxy :: Proxy "BTC")
+  , testExchangeRate (Proxy :: Proxy "VUV") (Proxy :: Proxy "USD")
+  , testExchangeRate (Proxy :: Proxy "VUV") (Proxy :: Proxy "VUV")
+  , testExchangeRate (Proxy :: Proxy "VUV") (Proxy :: Proxy "XAU")
+  , testExchangeRate (Proxy :: Proxy "XAU") (Proxy :: Proxy "BTC")
+  , testExchangeRate (Proxy :: Proxy "XAU") (Proxy :: Proxy "USD")
+  , testExchangeRate (Proxy :: Proxy "XAU") (Proxy :: Proxy "VUV")
+  , testExchangeRate (Proxy :: Proxy "XAU") (Proxy :: Proxy "XAU")
+  ]
+
+
+testDiscrete
+  :: forall (currency :: Symbol) (unit :: Symbol)
+  .  ( Money.GoodScale (Money.Scale currency unit)
+     , KnownSymbol currency
+     , KnownSymbol unit )
+  => Proxy currency
+  -> Proxy unit
+  -> Tasty.TestTree
+testDiscrete pc pu =
+  Tasty.testGroup ("Discrete " ++ show (symbolVal pc) ++ " "
+                               ++ show (symbolVal pu))
+  [ QC.testProperty "Aeson encoding roundtrip" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Discrete currency unit) ->
+         Just x === Ae.decode (Ae.encode x)
+  , QC.testProperty "Aeson encoding roundtrip (SomeDiscrete)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Discrete currency unit) ->
+         let x' = Money.toSomeDiscrete x
+         in Just x' === Ae.decode (Ae.encode x')
+  , QC.testProperty "Aeson encoding roundtrip (Discrete through SomeDiscrete)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Discrete currency unit) ->
+         Just x === Ae.decode (Ae.encode (Money.toSomeDiscrete x))
+  , QC.testProperty "Aeson encoding roundtrip (SomeDiscrete through Discrete)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Discrete currency unit) ->
+         Just (Money.toSomeDiscrete x) === Ae.decode (Ae.encode x)
+  , QC.testProperty "Aeson decoding of pre-0.4 format (Discrete, SomeDiscrete)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.Discrete currency unit) ->
+        let sx = Money.toSomeDiscrete x
+            c = T.unpack (Money.someDiscreteCurrency sx)
+            r = Money.someDiscreteScale sx
+            a = Money.someDiscreteAmount sx
+            bs = Ae.encode ("Discrete" :: String, c, numerator r, denominator r, a)
+        in (Just  x === Ae.decode bs) .&&.
+           (Just sx === Ae.decode bs)
+  ]
+
+testExchangeRate
+  :: forall (src :: Symbol) (dst :: Symbol)
+  .  (KnownSymbol src, KnownSymbol dst)
+  => Proxy src
+  -> Proxy dst
+  -> Tasty.TestTree
+testExchangeRate ps pd =
+  Tasty.testGroup ("ExchangeRate " ++ show (symbolVal ps) ++ " "
+                                   ++ show (symbolVal pd))
+  [ QC.testProperty "Aeson encoding roundtrip" $
+      QC.forAll QC.arbitrary $ \(x :: Money.ExchangeRate src dst) ->
+         Just x === Ae.decode (Ae.encode x)
+  , QC.testProperty "Aeson encoding roundtrip (SomeExchangeRate)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.ExchangeRate src dst) ->
+         let x' = Money.toSomeExchangeRate x
+         in Just x' === Ae.decode (Ae.encode x')
+  , QC.testProperty "Aeson encoding roundtrip (ExchangeRate through SomeExchangeRate)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.ExchangeRate src dst) ->
+         Just x === Ae.decode (Ae.encode (Money.toSomeExchangeRate x))
+  , QC.testProperty "Aeson encoding roundtrip (SomeExchangeRate through ExchangeRate)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.ExchangeRate src dst) ->
+         Just (Money.toSomeExchangeRate x) === Ae.decode (Ae.encode x)
+  , QC.testProperty "Aeson decoding of pre-0.4 format (ExchangeRate, SomeExchangeRate)" $
+      QC.forAll QC.arbitrary $ \(x :: Money.ExchangeRate src dst) ->
+        let sx = Money.toSomeExchangeRate x
+            src = T.unpack (Money.someExchangeRateSrcCurrency sx)
+            dst = T.unpack (Money.someExchangeRateDstCurrency sx)
+            r = Money.someExchangeRateRate sx
+            bs = Ae.encode ("ExchangeRate" :: String, src, dst, numerator r, denominator r)
+        in (Just  x === Ae.decode bs) .&&.
+           (Just sx === Ae.decode bs)
+  ]
+
+--------------------------------------------------------------------------------
+-- Raw parsing "golden tests"
+
+testRawSerializations :: Tasty.TestTree
+testRawSerializations =
+  Tasty.testGroup "Raw serializations"
+  [ Tasty.testGroup "aeson"
+    [ Tasty.testGroup "decode"
+      [ HU.testCase "Dense" $ Just rawDns0 @=? Ae.decode rawDns0_aeson
+      , HU.testCase "Discrete" $ Just rawDis0 @=? Ae.decode rawDis0_aeson
+      , HU.testCase "ExchangeRate" $ Just rawXr0 @=? Ae.decode rawXr0_aeson
+      ]
+    , Tasty.testGroup "decode (pre-0.4)"
+      [ HU.testCase "Dense" $ Just rawDns0 @=? Ae.decode rawDns0_aeson_pre04
+      , HU.testCase "Discrete" $ Just rawDis0 @=? Ae.decode rawDis0_aeson_pre04
+      , HU.testCase "ExchangeRate" $ Just rawXr0 @=? Ae.decode rawXr0_aeson_pre04
+      ]
+    , Tasty.testGroup "encode"
+      [ HU.testCase "Dense" $ rawDns0_aeson @=? Ae.encode rawDns0
+      , HU.testCase "Discrete" $ rawDis0_aeson @=? Ae.encode rawDis0
+      , HU.testCase "ExchangeRate" $ rawXr0_aeson @=? Ae.encode rawXr0
+      ]
+    ]
+  ]
+
+rawDns0 :: Money.Dense "USD"
+rawDns0 = Money.dense' (26%1)
+
+rawDis0 :: Money.Discrete "USD" "cent"
+rawDis0 = Money.discrete 4
+
+rawXr0 :: Money.ExchangeRate "USD" "BTC"
+Just rawXr0 = Money.exchangeRate (3%2)
+
+rawDns0_aeson :: BL.ByteString
+rawDns0_aeson = "[\"USD\",26,1]"
+rawDis0_aeson :: BL.ByteString
+rawDis0_aeson = "[\"USD\",100,1,4]"
+rawXr0_aeson :: BL.ByteString
+rawXr0_aeson = "[\"USD\",\"BTC\",3,2]"
+
+-- pre safe-money 0.4
+rawDns0_aeson_pre04 :: BL.ByteString
+rawDns0_aeson_pre04 = "[\"Dense\",\"USD\",26,1]"
+rawDis0_aeson_pre04 :: BL.ByteString
+rawDis0_aeson_pre04 = "[\"Discrete\",\"USD\",100,1,4]"
+rawXr0_aeson_pre04 :: BL.ByteString
+rawXr0_aeson_pre04 = "[\"ExchangeRate\",\"USD\",\"BTC\",3,2]"
+
