diff --git a/json-spec.cabal b/json-spec.cabal
--- a/json-spec.cabal
+++ b/json-spec.cabal
@@ -1,6 +1,6 @@
 cabal-version:       3.0
 name:                json-spec
-version:             1.1.0.0
+version:             1.1.1.0
 synopsis:            Type-level JSON specification
 maintainer:          rick@owensmurray.com
 description:         See the README at: https://github.com/owensmurray/json-spec#json-spec
diff --git a/src/Data/JsonSpec/Spec.hs b/src/Data/JsonSpec/Spec.hs
--- a/src/Data/JsonSpec/Spec.hs
+++ b/src/Data/JsonSpec/Spec.hs
@@ -32,7 +32,7 @@
 import Data.Time (UTCTime)
 import GHC.Records (HasField(getField))
 import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)
-import Prelude (($), Bool, Either, Eq, Int, Maybe, Show)
+import Prelude (Maybe(Just, Nothing), ($), Bool, Either, Eq, Int, Show)
 
 
 {-|
@@ -362,6 +362,13 @@
   deriving stock (Show, Eq)
 instance {-# overlappable #-} (HasField k more v) => HasField k (Field notIt x, more) v where
   getField (_, more) = getField @k @_ @v more
+instance {-# overlappable #-} (HasField k more v) => HasField k (Maybe (Field notIt x), more) v where
+  getField (_, more) = getField @k @_ @v more
+instance HasField k (Maybe (Field k v), more) (Maybe v) where
+  getField (mv, _) =
+    case mv of
+      Nothing -> Nothing
+      Just (Field v) -> Just v
 instance HasField k (Field k v, more) v where
   getField (Field v, _) = v
 
diff --git a/test/jsonspec.hs b/test/jsonspec.hs
--- a/test/jsonspec.hs
+++ b/test/jsonspec.hs
@@ -414,35 +414,80 @@
           in
             actual `shouldBe` expected
 
-      it "HasField" $
-        let
-          expected :: Maybe TestHasField
-          expected =
-            Just
-              TestHasField
-                { thfFoo = "foo"
-                , thfBar = 10
-                , thfBaz =
-                    TestSubObj
-                      { foo2 = "bar"
-                      , bar2 = negate 10
-                      }
-                }
+      describe "HasField" $ do
+        it "Basic HasField" $
+          let
+            expected :: Maybe TestHasField
+            expected =
+              Just
+                TestHasField
+                  { thfFoo = "foo"
+                  , thfBar = 10
+                  , thfBaz =
+                      TestSubObj
+                        { foo2 = "bar"
+                        , bar2 = negate 10
+                        }
+                  }
 
-          actual :: Maybe TestHasField
-          actual =
-            A.decode
-              "{\
-              \  \"foo\": \"foo\",\
-              \  \"bar\": 10,\
-              \  \"baz\": {\
-              \    \"a_string\": \"bar\",\
-              \    \"an_int\": -10\
-              \  }\
-              \}"
-        in
-          actual `shouldBe` expected
+            actual :: Maybe TestHasField
+            actual =
+              A.decode
+                "{\
+                \  \"foo\": \"foo\",\
+                \  \"bar\": 10,\
+                \  \"baz\": {\
+                \    \"a_string\": \"bar\",\
+                \    \"an_int\": -10\
+                \  }\
+                \}"
+          in
+            actual `shouldBe` expected
 
+        it "missing optional fields" $
+          let
+            expected :: Maybe TestOptionalHasField
+            expected =
+              Just
+                TestOptionalHasField
+                  { foo = Nothing
+                  , bar = Nothing
+                  }
+
+            actual :: Maybe TestOptionalHasField
+            actual = A.decode "{}"
+          in
+            actual `shouldBe` expected
+
+        it "supplied optional fields" $
+          let
+            expected :: Maybe TestOptionalHasField
+            expected =
+              Just
+                TestOptionalHasField
+                  { foo = Just "foo"
+                  , bar = Just Nothing
+                  }
+
+            actual :: Maybe TestOptionalHasField
+            actual = A.decode "{\"foo\": \"foo\", \"bar\": null}"
+          in
+            actual `shouldBe` expected
+        it "mixed optional fields" $
+          let
+            expected :: Maybe TestOptionalHasField
+            expected =
+              Just
+                TestOptionalHasField
+                  { foo = Nothing
+                  , bar = Just (Just "bar")
+                  }
+
+            actual :: Maybe TestOptionalHasField
+            actual = A.decode "{\"bar\": \"bar\"}"
+          in
+            actual `shouldBe` expected
+
       describe "mutual recursion" $ do
         describe "style1" $ do
           it "encodes" $
@@ -473,15 +518,15 @@
                 "{\"foo\":{\"bar\":{\"foo\":{\"bar\":{\"foo\":null}}}}}"
 
               actual =
-                A.encode 
+                A.encode
                   MRec3
                     { foo =
-                        Just 
+                        Just
                           MRec4
                             { bar =
                                 MRec3
                                   { foo =
-                                      Just 
+                                      Just
                                         MRec4
                                           { bar =
                                               MRec3
@@ -501,12 +546,12 @@
                 Just
                   MRec3
                     { foo =
-                        Just 
+                        Just
                           MRec4
                             { bar =
                                 MRec3
                                   { foo =
-                                      Just 
+                                      Just
                                         MRec4
                                           { bar =
                                               MRec3
@@ -607,6 +652,26 @@
       pure TestB
 
 
+data TestOptionalHasField = TestOptionalHasField
+  { foo :: Maybe Text
+  , bar :: Maybe (Maybe Text)
+  }
+  deriving stock (Show, Eq)
+  deriving FromJSON via (SpecJSON TestOptionalHasField)
+instance HasJsonDecodingSpec TestOptionalHasField where
+  type DecodingSpec TestOptionalHasField =
+    JsonObject
+     '[ "foo" ::? JsonString
+      , "bar" ::? JsonNullable JsonString
+      ]
+  fromJSONStructure v =
+    pure
+      TestOptionalHasField
+        { foo = v.foo
+        , bar = v.bar
+        }
+
+
 data TestObj = TestObj
   { foo :: Text
   , bar :: Maybe Scientific
@@ -951,7 +1016,7 @@
 instance HasJsonEncodingSpec MRec4 where
   type EncodingSpec MRec4 =
     JsonLet SharedRecSpecs (JsonRef "four")
-  toJSONStructure MRec4 { bar } = 
+  toJSONStructure MRec4 { bar } =
     Ref
       (Field @"bar" (toJSONStructure bar),
       ())
