diff --git a/ip.cabal b/ip.cabal
--- a/ip.cabal
+++ b/ip.cabal
@@ -1,5 +1,5 @@
 name:                ip
-version:             0.9
+version:             0.9.1
 synopsis:            Library for IP and MAC addresses
 homepage:            https://github.com/andrewthad/haskell-ip#readme
 license:             BSD3
diff --git a/src/Net/Types.hs b/src/Net/Types.hs
--- a/src/Net/Types.hs
+++ b/src/Net/Types.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE InstanceSigs #-}
@@ -29,6 +30,8 @@
 import qualified Data.Vector.Generic.Mutable    as MGVector
 import qualified Data.Vector.Unboxed.Mutable    as MUVector
 import qualified Data.Vector.Primitive.Mutable  as MPVector
+import qualified Data.Text.Encoding as TE
+import qualified Data.ByteString.Builder as BB
 import Data.Word.Synthetic (Word48)
 import Data.Primitive.Types (Prim)
 import Data.Bits (Bits,FiniteBits,(.|.),unsafeShiftL)
@@ -40,6 +43,12 @@
 import Data.Aeson (FromJSON(..),ToJSON(..))
 import GHC.Generics (Generic)
 
+#if MIN_VERSION_aeson(1,0,0) 
+import qualified Data.Aeson.Encoding as Aeson
+import Data.Aeson (ToJSONKey(..),FromJSONKey(..),
+  ToJSONKeyFunction(..),FromJSONKeyFunction(..))
+#endif
+
 -- | A 32-bit Internet Protocol version 4 address.
 newtype IPv4 = IPv4 { getIPv4 :: Word32 }
   deriving (Eq,Ord,Show,Read,Enum,Bounded,Hashable,Generic,Prim,Bits,FiniteBits)
@@ -94,6 +103,28 @@
 
 instance ToJSON Mac where
   toJSON (Mac w) = Aeson.String (Internal.macToTextDefault w)
+
+#if MIN_VERSION_aeson(1,0,0) 
+instance ToJSONKey Mac where
+  toJSONKey = ToJSONKeyText
+    (\(Mac w) -> Internal.macToTextDefault w)
+    (\(Mac w) -> Aeson.unsafeToEncoding $ BB.byteString $ TE.encodeUtf8 $ Internal.macToTextDefault w)
+
+instance FromJSONKey Mac where
+  fromJSONKey = FromJSONKeyTextParser $ \t -> 
+    case Internal.macFromText (Just ':') macFromOctets' t of
+      Nothing -> fail "invalid mac address"
+      Just mac -> return mac
+
+instance ToJSONKey IPv4 where
+  toJSONKey = ToJSONKeyText
+    (\(IPv4 w) -> Internal.toDotDecimalText w)
+    (\(IPv4 w) -> Aeson.unsafeToEncoding $ BB.byteString $ TE.encodeUtf8 $ Internal.toDotDecimalText w)
+
+instance FromJSONKey IPv4 where
+  fromJSONKey = FromJSONKeyTextParser
+    (Internal.eitherToAesonParser . coerce Internal.decodeIPv4TextEither)
+#endif
 
 instance FromJSON Mac where
   parseJSON = Internal.attoparsecParseJSON
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -25,6 +25,7 @@
 import qualified Net.Mac.ByteString.Char8 as MacByteString
 
 import qualified Data.Attoparsec.Text as AT
+import qualified Data.Attoparsec.ByteString as AB
 
 import ArbitraryInstances ()
 import qualified Naive
@@ -78,6 +79,9 @@
       [ testProperty "Identical to Naive"
           $ propMatching IPv4ByteString.encode Naive.encodeByteString
       ]
+    , testGroup "IPv4 encode/decode"
+      [ testCase "Parser Test Cases" testIPv4Parser
+      ]
     , testGroup "IPv6 encode/decode"
       [ testCase "Parser Test Cases" testIPv6Parser
       ]
@@ -138,6 +142,18 @@
   go a b c d e f str =
     Just (HexMac (Mac.fromOctets a b c d e f))
     @?= fmap HexMac (MacByteString.decodeLenient (BC8.pack str))
+
+testIPv4Parser :: Assertion
+testIPv4Parser = do
+  go 202 10 19 54 "202.10.19.54"
+  go 10 202 96 25 "10.202.96.25"
+  where
+  go a b c d str =
+    Right (IPv4.fromOctets a b c d)
+    @?= (AB.parseOnly
+          (IPv4ByteString.parser <* AT.endOfInput)
+          (BC8.pack str)
+        )
 
 testIPv6Parser :: Assertion
 testIPv6Parser = do
