diff --git a/Text/JSON.hs b/Text/JSON.hs
--- a/Text/JSON.hs
+++ b/Text/JSON.hs
@@ -1,4 +1,4 @@
-{-# OPTIONS_GHC -XCPP -XMultiParamTypeClasses -XTypeSynonymInstances #-}
+{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances #-}
 --------------------------------------------------------------------
 -- |
 -- Module    : Text.JSON
@@ -50,19 +50,17 @@
 
     -- ** Instance helpers
   , makeObj, valFromObj
+  , JSKey(..), encJSDict, decJSDict
   
   ) where
 
 import Text.JSON.Types
 import Text.JSON.String
 
-import Data.List
 import Data.Int
 import Data.Word
-import Data.Either
 import Control.Monad(liftM,ap,MonadPlus(..))
 import Control.Applicative
-import Control.Monad.Error ( MonadError(..) )
 
 import qualified Data.ByteString.Char8 as S
 import qualified Data.ByteString.Lazy.Char8 as L
@@ -156,12 +154,6 @@
   Ok a >>= f    = f a
   Error x >>= _ = Error x
 
-instance MonadError String Result where
-  throwError x = Error x
-
-  catchError (Error e) h = h e
-  catchError x _ = x
-
 -- | Convenient error generation
 mkError :: String -> Result a
 mkError s = Error s
@@ -369,27 +361,27 @@
 
 -- container types:
 
-instance (Ord a, JSON a, JSON b) => JSON (M.Map a b) where
 #if !defined(MAP_AS_DICT)
+instance (Ord a, JSON a, JSON b) => JSON (M.Map a b) where
   showJSON = encJSArray M.toList
   readJSON = decJSArray "Map" M.fromList
-#else
-  showJSON = encJSDict M.toList
-   -- backwards compatibility..
-  readJSON a@JSArray{}  = M.fromList <$> readJSON a
-  readJSON o = decJSDict "Map" M.fromList o
-#endif
 
 instance (JSON a) => JSON (IntMap.IntMap a) where
-#if !defined(MAP_AS_DICT)
   showJSON = encJSArray IntMap.toList
   readJSON = decJSArray "IntMap" IntMap.fromList
+
 #else
-{- alternate (dict) mapping: -}
-  showJSON = encJSDict IntMap.toList
-  readJSON = decJSDict "IntMap" IntMap.fromList
+instance (Ord a, JSKey a, JSON b) => JSON (M.Map a b) where
+  showJSON    = encJSDict . M.toList
+  readJSON o  = M.fromList <$> decJSDict "Map" o
+
+instance (JSON a) => JSON (IntMap.IntMap a) where
+  {- alternate (dict) mapping: -}
+  showJSON    = encJSDict . IntMap.toList
+  readJSON o  = IntMap.fromList <$> decJSDict "IntMap" o
 #endif
 
+
 instance (Ord a, JSON a) => JSON (Set.Set a) where
   showJSON = encJSArray Set.toList
   readJSON = decJSArray "Set" Set.fromList
@@ -454,22 +446,42 @@
 decJSArray _ f a@JSArray{} = f <$> readJSON a
 decJSArray l _ _ = mkError ("readJSON{"++l++"}: unable to parse array value")
 
-#if defined(MAP_AS_DICT)
-encJSDict :: (JSON a, JSON b) => (c -> [(a,b)]) -> c -> JSValue
-encJSDict f v = makeObj $ 
-  map (\ (x,y) -> (showJSValue (showJSON x) "", showJSON y)) (f v)
+-- | Haskell types that can be used as keys in JSON objects.
+class JSKey a where
+  toJSKey   :: a -> String
+  fromJSKey :: String -> Maybe a
 
-decJSDict :: (JSON a, JSON b)
+instance JSKey JSString where
+  toJSKey x   = fromJSString x
+  fromJSKey x = Just (toJSString x)
+
+instance JSKey Int where
+  toJSKey   = show
+  fromJSKey key = case reads key of
+                    [(a,"")] -> Just a
+                    _        -> Nothing
+
+-- NOTE: This prevents us from making other instances for lists but,
+-- our guess is that strings are used as keys more often then other list types.
+instance JSKey String where
+  toJSKey   = id
+  fromJSKey = Just
+  
+-- | Encode an association list as 'JSObject' value.
+encJSDict :: (JSKey a, JSON b) => [(a,b)] -> JSValue
+encJSDict v = makeObj [ (toJSKey x, showJSON y) | (x,y) <- v ]
+
+-- | Decode a 'JSObject' value into an association list.
+decJSDict :: (JSKey a, JSON b)
           => String
-	  -> ([(a,b)] -> c)
 	  -> JSValue
-	  -> Result c
-decJSDict _ f (JSObject o) = mapM rd (fromJSObject o) >>= return . f
-   where
-     rd (a,b) = do
-       pa <- decode a
-       pb <- readJSON b
-       return (pa,pb)
-decJSDict l _ _ = mkError ("readJSON{"++l ++ "}: unable to read dict; expected JSON object")
-#endif
+	  -> Result [(a,b)]
+decJSDict l (JSObject o) = mapM rd (fromJSObject o)
+  where rd (a,b) = case fromJSKey a of
+                     Just pa -> readJSON b >>= \pb -> return (pa,pb)
+                     Nothing -> mkError ("readJSON{" ++ l ++ "}:" ++
+                                    "unable to read dict; invalid object key")
+
+decJSDict l _ = mkError ("readJSON{"++l ++ "}: unable to read dict; expected JSON object")
+
 
diff --git a/Text/JSON/Generic.hs b/Text/JSON/Generic.hs
--- a/Text/JSON/Generic.hs
+++ b/Text/JSON/Generic.hs
@@ -26,8 +26,6 @@
     ) where
 
 import Control.Monad.State
-import Control.Monad.Identity
-import Data.Maybe
 import Text.JSON
 import Text.JSON.String ( runGetJSON )
 import Data.Generics
diff --git a/Text/JSON/Parsec.hs b/Text/JSON/Parsec.hs
--- a/Text/JSON/Parsec.hs
+++ b/Text/JSON/Parsec.hs
@@ -109,7 +109,7 @@
 (*>)    = (>>)
 
 (<*)   :: CharParser () a -> CharParser () b -> CharParser () a
-m <* n  = do x <- m; n; return x
+m <* n  = do x <- m; _ <- n; return x
 
 empty  :: CharParser () a
 empty   = mzero
diff --git a/Text/JSON/ReadP.hs b/Text/JSON/ReadP.hs
--- a/Text/JSON/ReadP.hs
+++ b/Text/JSON/ReadP.hs
@@ -101,7 +101,7 @@
 (*>)    = (>>)
 
 (<*)   :: ReadP a -> ReadP b -> ReadP a
-m <* n  = do x <- m; n; return x
+m <* n  = do x <- m; _ <- n; return x
 
 empty  :: ReadP a
 empty   = pfail
diff --git a/json.cabal b/json.cabal
--- a/json.cabal
+++ b/json.cabal
@@ -1,5 +1,5 @@
 name:               json
-version:            0.4.4
+version:            0.5
 synopsis:           Support for serialising Haskell to and from JSON
 description:
     JSON (JavaScript Object Notation) is a lightweight data-interchange
@@ -90,7 +90,7 @@
 
   if flag(split-base)
     if flag(generic)
-      build-depends:    base >=4 && <5, syb
+      build-depends:    base >=4 && <5, syb >= 0.3.3
 
       exposed-modules:  Text.JSON.Generic
       Cpp-Options:      -DBASE_4
