diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,175 @@
+This is some documentation on how to use the library.  I wrote a blog
+post about an older version of the library which may contain some
+useful information on using syb-with-class:
+
+http://lingnerd.blogspot.com/2007/12/pushing-haskells-type-system-to-limits.html
+
+------------------------------------------------------------------------
+
+Not all features of the library are covered in this document yet.
+Unfortunately, the haddock documentation will not build at the moment
+because of the Template Haskell code in RJson.hs. You might want to
+look at Text/RJson.hs to check out the Haddock comments for the
+methods of ToJson and FromJson.
+
+------------------------------------------------------------------------
+
+Suppose we have the following datatypes:
+
+    data TestRecord2 = TestRecord2 {
+       _c :: Int,
+       _d :: String
+    } deriving Show
+
+    data TestRecord1 = TestRecord1 {
+       _a :: String,
+       _b :: TestRecord2
+    } deriving Show
+
+In order to use RJson, we first have to derive instances of Data and
+Typeable for these types.  The following options/modules are required:
+
+    {-# OPTIONS_GHC
+     -XTemplateHaskell
+     -XFlexibleInstances
+     -XMultiParamTypeClasses
+     -XFlexibleContexts
+     -XUndecidableInstances #-}
+    import Text.RJson
+    import Data.Generics.SYB.WithClass.Basics
+    import Data.Generics.SYB.WithClass.Derive
+
+The following Template Haskell code can be used to derive the
+instances automatically:
+
+    $(derive[''TestRecord1, ''TestRecord2])
+
+Now we can use the 'toJson' function to serialize TestRecord1 and
+TestRecord2 structures. For example, the expression
+
+    toJson (TestRecord1 { _a="foo", _b=TestRecord2 { _c=5, _d="bar"}})
+
+will evaluate to the following JsonData object:
+
+    {"a":"foo","b":{"c":5,"d":"bar"}
+
+You can just pass this object to 'show' to convert it to a string, or
+use the 'toJsonString' utility function. The current implementation of
+'show' outputs ASCII-only strings, using "\uXXXX" escape sequences for
+unicode characters.  Note that the initial underscores have been
+stripped from the field names.  This is the default behavior, but we
+could override it by adding an instance to the TranslateField class:
+
+    instance TranslateField TestRecord1 where
+        translateField _dummy x = x
+    instance TranslateField TestRecord2 where
+        translateField _dummy x = x
+
+Now if we call 'toJson', the underscores will not be removed:
+
+    {"_a":"foo","_b":{"_c":5,"_d":"bar"}
+
+The 'fromJson' function is used to deserialize a JsonData object.
+Usually, it is easier to use 'fromJsonString', which parses a string
+to a JsonData object and then passes the result to 'fromJson'. The
+following expression will evaluate to Just the same TestRecord1
+structure that we passed to 'toJson' earlier:
+
+    fromJsonString (undefined :: TestRecord1) "{\"_a\":\"foo\",\"_b\":{\"_c\":5,\"_d\":\"bar\"}}"
+    --> Right (TestRecord1 { _a="foo", _b=TestRecord2 { _c=5, _d="bar"}})
+
+The first parameter of 'fromJsonString' (and 'fromJson') is a dummy
+value specifying the type of the record which is being deserialized.
+Note that the preceding instance of TranslateField is in effect here
+(the JSON object keys begin with underscores).
+
+The 'fromJsonString' function assumes that the string it is passed is
+a true unicode string. For this reason, if you have obtained your JSON
+String using the standard Haskell IO libraries, you may not get the
+correct behavior with unicode strings (since your String will be a
+sequence of bytes rather than code points). It is usually better to
+get the raw JSON data into a ByteString and then use
+'fromJsonByteString', which automatically detects and decodes unicode
+strings.
+
+The JsonData type has the following definition:
+
+    data JsonData = JDString String                          |
+                    JDNumber Double                          |
+                    JDArray [JsonData]                       |
+                    JDBool Bool                              |
+                    JDObject (Data.Map.Map String JsonData)
+
+You can implement custom serialization and deserialization behavior
+by adding instances to the ToJson and FromJson classes respectively.
+Suppose that we have the following enum type:
+
+    data Direction = Forward | Back | Left | Right deriving Show
+    $(derive[''Direction])
+
+As will be explained shortly, the default serialization behavior is
+for the values of this enum to be converted to empty JSON lists, which
+is probably not what you want. In order to convert them to and from
+the appropriate strings, the following instance definitions can be
+added:
+
+    instance ToJson Direction where
+        toJson North   = JDString "north"
+        toJson South   = JDString "south"
+        toJson East    = JDString "east"
+        toJson West    = JDString "west"
+    instance FromJson Direction where
+        fromJson _dummy (JDString "north")  = Right North
+        fromJson _dummy (JDString "south")  = Right South
+        fromJson _dummy (JDString "east")   = Right East
+        fromJson _dummy (JDString "west")   = Right West
+        fromJson _dummy _                   = Left "Deserialization error for 'Direction'"
+
+In fact, RJson provides 'enumToJson' and 'enumFromJson' functions
+which automate the definition of instances of this sort. The preceding
+instance definitions could equivalently be written as follows:
+
+    instance ToJson Direction where
+        toJson = enumToJson firstCharToLower
+    instance FromJson Direction where
+        fromJson = enumFromJson firstCharToUpper
+
+The first arguments to 'enumToJson' and 'enumFromJson' are
+(String->String) functions used for converting Haskell enum
+constructor names to JSON strings and vice versa. The functions
+'firstCharToUpper' and 'firstCharToLower' are provided by RJson.
+
+Default serialization behavior is as follows:
+
+    Haskell primitive types  <-->  Corresponding JSON type
+    Haskell records          <-->  JSON objects
+    Haskell tupels           <-->  Heterogenous JSON arrays
+    Haskell algebraic types  <-->  JSON array of arguments given to
+                                   constructor. First constructor
+                                   always used when deserializing.
+                                   (Not a very useful default.)
+
+Both ToJson and FromJson have some other methods which can be used to
+customize serialization behavior (check the Haddock
+documentation). For example, you can specify default field values for
+JSON objects.  Note that there is no default implementation of the
+'toJson' or 'fromJson' methods, so if you are overriding other methods
+in an instance declaration of ToJson or FromJson, you can set 'toJson'
+and 'fromJson' to 'genericToJson' and 'genericFromJson' respectively
+in order to get the default behavior.
+
+The 'Union' type can be used to implement a kind of crude inheritance
+for Haskell record types.  The type has a single binary constructor
+('Union'). Unions are serialized by serializing each of the arguments
+to the constructor, then merging the resulting JSON objects into a
+single object.  If any of the arguments of the constructor does not
+serialize to a JSON object then a runtime error will occur.  To create
+unions of more than two records, just use `Union` as an infix
+constructor.  Type synonyms are defined for complex unions of this
+kind (Union3 a b c, Union4 a b c d, etc. etc.)
+
+WARNING: Record types with strict constructors will lead to runtime
+errors when using 'fromJson' ('toJson' will still work fine). This is
+because it seems to be necessary to temporarily create records with
+dummy field values. If the fields are strict, these dummy values get
+evaluated, leading to an exception being raised.
diff --git a/RJson.cabal b/RJson.cabal
--- a/RJson.cabal
+++ b/RJson.cabal
@@ -1,5 +1,5 @@
 Name:          RJson
-Version:       0.3.2
+Version:       0.3.3
 Cabal-Version: >= 1.2
 License:       BSD3
 License-File:  LICENSE
@@ -8,8 +8,11 @@
 Category:      Text
 Synopsis:      A reflective JSON serializer/parser.
 Stability:     experimental
+Extra-Source-Files:   README
+Build-Type:    Simple
 
 Description:
+  See included README for some examples.
   This package uses the Scrap Your Boilerplate With Class approach
   to generics to implement a reflective Json serializer and deserializer.
   Nested record types can be automatically converted to corresponding
diff --git a/Text/RJson.hs b/Text/RJson.hs
--- a/Text/RJson.hs
+++ b/Text/RJson.hs
@@ -6,7 +6,6 @@
     -XUndecidableInstances
     -XTemplateHaskell
     -cpp #-}
-
 module Text.RJson (TranslateField,
                    TranslateFieldD,
                    translateField,
@@ -25,6 +24,7 @@
                    objectDefaults,
                    parseJsonString,
                    parseJsonByteString,
+                   fromJson,
                    fromJsonString,
                    fromJsonByteString,
                    genericFromJson,
@@ -194,9 +194,7 @@
 toJsonProxy :: Proxy ToJsonD
 toJsonProxy = error "'toJsonProxy' value should never be evaluated!"
 
--- Again, note inclusion of translateField from TranslateField,
--- and TranslateField qualification on variable 't' (in addition
--- to the expected ToJson qualification).
+-- Again, note inclusion of translateField from TranslateField.
 instance ToJson t => Sat (ToJsonD t) where
     dict = ToJsonD { toJsonD          = toJson,
                      excludeD         = exclude,
@@ -301,7 +299,7 @@
     toJson = genericToJson
 
 -- Instances for tuples up to n=7 (this limit it is set by the non-existence of Typeable8).
--- Tuples are converted to (hetrogenous) JSON lists.
+-- Tuples are converted to (heterogenous) JSON lists.
 #define I(x) ToJson x, Typeable x
 instance (I(a), I(b)) => ToJson (a, b) where
     toJson (a,b) = JDArray [toJson a, toJson b]
@@ -345,6 +343,7 @@
 fromJsonProxy :: Proxy FromJsonD
 fromJsonProxy = error "'fromJsonProxy' should never be evaluated!"
 
+-- Note inclusion of translateField from TranslateField.
 instance FromJson t => Sat (FromJsonD t) where
     dict = FromJsonD { fromJsonD = fromJson,
                        objectDefaultsD = objectDefaults,
@@ -399,7 +398,7 @@
         in
           if isRight r1 && isRight r2
              then Right $ Union (fromRight r1) (fromRight r2)
-             else Left "Bad fromJson conversion: error constructing subpart of union"
+             else Left "Bad fromJson conversion: error constructing subpart of union (did not serialize to object)"
     fromJson _ _ = Left "Bad fromJson conversion: attempt to convert non-object to Union"
 
 tuperror :: Int -> Either String a
@@ -484,18 +483,18 @@
 
 -- TODO: Again, uninformative name.
 -- TODO: Some code duplication here.
-m2 :: (Data FromJsonD a) => M.Map String JsonData -> a -> ErrorWithState String (M.Map String JsonData, [String]) a
-m2 defaults dummy = do
+m2 :: (Data FromJsonD a, TranslateField a) => M.Map String JsonData -> (String -> String) -> a -> ErrorWithState String (M.Map String JsonData, [String]) a
+m2 defaults transFunc dummy = do
   (m, sl) <- lift get
   (case sl of
      []     -> throwError "Bad fromJson conversion: Not enough fields in JSON object to satisfy constructor"
      (f:fs) -> do
        lift $ put (m, fs)
-       let stripped = translateFieldD'' dict dummy f
+       let stripped = transFunc f
        (case M.lookup stripped m of
           Nothing ->
             case M.lookup stripped defaults of
-              Nothing -> throwError $  "Bad fromJson conversion: Required field not present in JSON object: "
+              Nothing -> throwError $  "Bad fromJson conversion: Required field not present in JSON object: " ++ stripped
               Just v  ->
                 case fromJsonD dict dummy v of
                   Left e  -> throwError e
@@ -505,7 +504,7 @@
               Left e  -> throwError e
               Right x -> return x))
 
-genericFromJson :: (Data FromJsonD a, Data TranslateFieldD a) => a -> JsonData -> Either String a
+genericFromJson :: (Data FromJsonD a, FromJson a, TranslateField a) => a -> JsonData -> Either String a
 genericFromJson dummy (JDArray l) =
     case datarep (dataTypeOf fromJsonProxy dummy) of
       AlgRep (c:_) ->
@@ -520,7 +519,7 @@
             -- Can't use fromConstrM because we need to get dummy values of the
             -- appropriate type for each argument of the constructor. This is unfortunate,
             -- since it means that we get runtime errors for records with strict fields.
-            fs -> evalState (runErrorT (gmapM fromJsonProxy (m2 (objectDefaultsD dict dummy)) (fromConstr fromJsonProxy c))) (m, fs)
+            fs -> evalState (runErrorT (gmapM fromJsonProxy (m2 (objectDefaultsD dict dummy) (translateFieldD'' dict dummy)) (fromConstr fromJsonProxy c))) (m, fs)
       AlgRep _     -> Left "Bad fromJson conversion: Type with no constructors!"
       _            -> Left "Bad fromJson conversion: Non-algebraic datatype given to 'genericFromJson'"
 genericFromJson _ _ = Left "Bad fromJson conversion: Expecting JSON object or array"
@@ -540,7 +539,7 @@
        else Left "Constructor name not recognized in enumFromJson"
 enumFromJson _ _ _ = Left "Non-string given to enumFromJson"
           
-instance (Data FromJsonD t, Data TranslateFieldD t) => FromJson t where
+instance (Data FromJsonD t, TranslateField t) => FromJson t where
     fromJson = genericFromJson
 
 
@@ -576,7 +575,7 @@
         -- If we can't figure it out, guess at UTF-8.
         else "UTF-8"
 
--- Converts a String of byte values of given encoding to a String of unicode code points.
+-- Converts a ByteString to a String of unicode code points.
 toHaskellString :: EncodingName -> B.ByteString -> String
 toHaskellString enc source =
     stripBOM $ map chr (pairBytes (B.unpack bs))
