diff --git a/chronologique.cabal b/chronologique.cabal
--- a/chronologique.cabal
+++ b/chronologique.cabal
@@ -1,6 +1,6 @@
 cabal-version:       >= 1.10
 name:                chronologique
-version:             0.3.0.1
+version:             0.3.1.1
 synopsis:            Time to manipulate time
 description:
  A simple type useful for representing timestamps as generated by system
@@ -35,7 +35,9 @@
   build-depends:     base >= 4.9 && < 5,
                      time,
                      hourglass,
-                     vector
+                     vector,
+                     text,
+                     aeson
 
   hs-source-dirs:    lib
 
@@ -74,6 +76,8 @@
                      hourglass,
                      QuickCheck,
                      vector,
+                     bytestring,
+                     aeson,
                      chronologique
 
   hs-source-dirs:    tests
diff --git a/lib/Chrono/TimeStamp.hs b/lib/Chrono/TimeStamp.hs
--- a/lib/Chrono/TimeStamp.hs
+++ b/lib/Chrono/TimeStamp.hs
@@ -9,6 +9,7 @@
 -- the 3-clause BSD licence.
 --
 
+{-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE InstanceSigs #-}
 {-# LANGUAGE TupleSections #-}
@@ -25,12 +26,17 @@
 ) where
 
 import Control.Applicative
+import Data.Aeson
+import Data.Aeson.Types (typeMismatch)
+import Data.Aeson.Encoding (string)
 import Data.Maybe
 import Data.Int (Int64)
 import Data.Hourglass
+import qualified Data.Text as T
 import qualified Data.Vector.Generic as G
 import qualified Data.Vector.Generic.Mutable as M
 import Data.Vector.Unboxed
+import GHC.Generics
 import Time.System
 
 import Chrono.Formats
@@ -78,7 +84,7 @@
 --
 newtype TimeStamp = TimeStamp {
     unTimeStamp :: Int64
-} deriving (Eq, Ord, Enum, Num, Real, Integral, Bounded)
+} deriving (Eq, Ord, Enum, Num, Real, Integral, Bounded, Generic)
 
 {-
     Hourglass works by sending types in and out of the Timeable and Time
@@ -105,25 +111,28 @@
 
 
 instance Show TimeStamp where
-    show t =
-        timePrint ISO8601_Precise t
+    show t = timePrint ISO8601_Precise t
 
 instance Read TimeStamp where
-    readsPrec _ s = maybeToList $ (,"") <$> reduceDateTime <$> parse s
-      where
-        parse :: String -> Maybe DateTime
-        parse x =   timeParse ISO8601_Precise x
-                <|> timeParse ISO8601_Seconds x
-                <|> timeParse ISO8601_DateAndTime x -- from hourglass
-                <|> timeParse ISO8601_Date x        -- from hourglass
-                <|> timeParse Posix_Precise x
-                <|> timeParse Posix_Micro x
-                <|> timeParse Posix_Milli x
-                <|> timeParse Posix_Seconds x
+    readsPrec _ s = maybeToList $ (,"") <$> parseInput s
 
-reduceDateTime :: DateTime -> TimeStamp
-reduceDateTime = timeFromElapsedP . timeGetElapsedP
+parseInput :: String -> Maybe TimeStamp
+parseInput = fmap reduceDateTime . parse
+  where
+    parse :: String -> Maybe DateTime
+    parse x =
+            timeParse ISO8601_Precise x
+        <|> timeParse ISO8601_Seconds x
+        <|> timeParse ISO8601_DateAndTime x -- from hourglass
+        <|> timeParse ISO8601_Date x        -- from hourglass
+        <|> timeParse Posix_Precise x
+        <|> timeParse Posix_Micro x
+        <|> timeParse Posix_Milli x
+        <|> timeParse Posix_Seconds x
 
+    reduceDateTime :: DateTime -> TimeStamp
+    reduceDateTime = timeFromElapsedP . timeGetElapsedP
+
 --
 -- | Get the current system time, expressed as a 'TimeStamp' (which is to
 -- say, number of nanoseconds since the Unix epoch).
@@ -176,4 +185,23 @@
     {-# INLINE basicUnsafeWrite #-}
 
 deriving instance Unbox TimeStamp
+
+{-
+    JSON encoding and decoding
+-}
+
+instance ToJSON TimeStamp where
+    toEncoding = string . timePrint ISO8601_Precise
+
+instance FromJSON TimeStamp where
+    parseJSON (String value) =
+      let
+        str = T.unpack value
+        result = parseInput str
+      in
+        case result of
+            Just t  -> pure t
+            Nothing -> fail "Unable to parse input as a TimeStamp"
+
+    parseJSON (invalid) = typeMismatch "TimeStamp" invalid
 
diff --git a/tests/CheckTimeStamp.hs b/tests/CheckTimeStamp.hs
--- a/tests/CheckTimeStamp.hs
+++ b/tests/CheckTimeStamp.hs
@@ -17,6 +17,8 @@
 
 module CheckTimeStamp where
 
+import Data.Aeson
+import qualified Data.ByteString.Lazy.Char8 as L
 import Test.Hspec
 import Test.QuickCheck
 import Data.Hourglass
@@ -102,13 +104,27 @@
             show (convertToUTC t) `shouldBe` "2014-07-31 23:23:35.948797001 UTC"
 
         it "behaves when QuickChecked" $ do
-            property prop_RoundTrip
+            property prop_RoundTrip_ReadShow
 
+    describe "Round trip via JSON" $ do
+        it "explicit JSON encoding is correct" $ do
+            let t = read "2018-05-01T01:42:12Z" :: TimeStamp
+            encode t `shouldBe` L.pack "\"2018-05-01T01:42:12.000000000Z\""
 
+        it "converts to a JSON String and back again" $ do
+            let t = read "2018-05-01T01:42:12Z" :: TimeStamp
+            (decode . encode) t `shouldBe` Just t
+
+        it "behaves when QuickChecked" $ do
+            property prop_RoundTrip_Aeson
+
 instance Arbitrary TimeStamp where
     arbitrary = do
         tick <- arbitrary
         return (TimeStamp tick)
 
-prop_RoundTrip :: TimeStamp -> Bool
-prop_RoundTrip t = (read . show) t == t
+prop_RoundTrip_ReadShow :: TimeStamp -> Bool
+prop_RoundTrip_ReadShow t = (read . show) t == t
+
+prop_RoundTrip_Aeson :: TimeStamp -> Bool
+prop_RoundTrip_Aeson t = (decode . encode) t == Just t
diff --git a/tests/Experiment.hs b/tests/Experiment.hs
--- a/tests/Experiment.hs
+++ b/tests/Experiment.hs
@@ -4,8 +4,26 @@
 module Main where
 
 import Chrono.TimeStamp
+import Data.Aeson
+import Data.ByteString.Builder
+import qualified Data.ByteString.Lazy.Char8 as L
+import qualified Data.Text.IO as T
+import System.IO
 
+x :: L.ByteString
+x = "2018-05-01T01:42:12Z"
+t = read (L.unpack x) :: TimeStamp
+j = toEncoding t
+
 main :: IO ()
 main = do
-    putStrLn "Hello"
- 
+    putStrLn . show . unTimeStamp $ t
+    putStrLn . show . toJSON $ t
+    L.putStrLn . toLazyByteString . fromEncoding . toEncoding $ t
+    L.putStrLn . encode $ t
+
+    putStrLn . show . (decode :: L.ByteString -> Maybe TimeStamp) . encode $ t
+    putStrLn . show . (eitherDecode :: L.ByteString -> Either String TimeStamp) $ "234"
+    putStrLn . show . (eitherDecode :: L.ByteString -> Either String TimeStamp) $ L.concat ["\"", x, "\""]
+    putStrLn . show . (eitherDecode :: L.ByteString -> Either String TimeStamp) $ L.concat ["\"", "2018-05:01T01:42:12Z" , "\""]
+
