diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Change Log
 
+## [0.0.2.1] - 2022-08-09
+
+- Fix `firstgid` field name in embedded tilesets.
+- Minimal `aeson` version is actually 2.0 (due to `KeyMap`).
+- `empty` values added for many «sparse» types.
+
 ## [0.0.2.0] - 2022-05-04
 
 Massive rewrite for Tiled 1.8.
@@ -16,6 +22,7 @@
 
 Initial release.
 
+[0.0.2.1]: https://github.com/haskell-game/aeson-tiled/releases/tag/v0.0.2.1
 [0.0.2.0]: https://github.com/haskell-game/aeson-tiled/releases/tag/v0.0.2.0
 [0.0.1.0]: https://github.com/haskell-game/aeson-tiled/releases/tag/v0.0.1.0
 [0.0.0.1]: https://github.com/haskell-game/aeson-tiled/releases/tag/v0.0.0.1
diff --git a/aeson-tiled.cabal b/aeson-tiled.cabal
--- a/aeson-tiled.cabal
+++ b/aeson-tiled.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: aeson-tiled
-version: 0.0.2.0
+version: 0.0.2.1
 synopsis: Aeson instances for the Tiled map editor.
 description:
   The mighty Tiled 2D map editor is an open source
@@ -56,7 +56,7 @@
   build-depends:
       base       >= 4.7 && < 5
     , bytestring >= 0.10 && < 1
-    , aeson      >= 1.0 && < 3
+    , aeson      >= 2.0 && < 3
     , containers >= 0.5 && < 1
     , text       >= 1.2 && < 3
     , vector     >= 0.11 && < 1
diff --git a/src/Codec/Tiled/Layer.hs b/src/Codec/Tiled/Layer.hs
--- a/src/Codec/Tiled/Layer.hs
+++ b/src/Codec/Tiled/Layer.hs
@@ -1,5 +1,13 @@
-module Codec.Tiled.Layer where
+module Codec.Tiled.Layer
+  ( Layer(..)
+  , empty
 
+  , pattern TILELAYER
+  , pattern OBJECTGROUP
+  , pattern IMAGELAYER
+  , pattern GROUP
+  ) where
+
 import Data.Text (Text)
 import Data.Vector (Vector)
 import GHC.Generics (Generic)
@@ -11,30 +19,30 @@
 import Codec.Tiled.Property (Property)
 
 data Layer = Layer
-  { chunks           :: Maybe (Vector Chunk)    -- ^ Array of chunks (optional). tilelayer only.
-  , compression      :: Maybe Text              -- ^ @zlib@, @gzip@, @zstd@ or empty (default). tilelayer only.
-  , data_            :: Maybe LayerData         -- ^ Array of unsigned int (GIDs) or base64-encoded data. tilelayer only.
-  , draworder        :: Maybe Text              -- ^ @topdown@ (default) or @index@. objectgroup only.
-  , encoding         :: Maybe Text              -- ^ @csv@ (default) or @base64@. tilelayer only.
+  { chunks           :: Maybe (Vector Chunk)    -- ^ Array of chunks (optional). @tilelayer@ only.
+  , compression      :: Maybe Text              -- ^ @zlib@, @gzip@, @zstd@ or empty (default). @tilelayer@ only.
+  , data_            :: Maybe LayerData         -- ^ Array of unsigned int (GIDs) or base64-encoded data. @tilelayer@ only.
+  , draworder        :: Maybe Text              -- ^ @topdown@ (default) or @index@. @objectgroup@ only.
+  , encoding         :: Maybe Text              -- ^ @csv@ (default) or @base64@. @tilelayer@ only.
   , height           :: Maybe Int               -- ^ Row count. Same as map height for fixed-size maps.
   , id               :: Maybe Int               -- ^ Incremental ID - unique across all layers
-  , image            :: Maybe FilePath          -- ^ Image used by this layer. imagelayer only.
-  , layers           :: Maybe (Vector Layer)    -- ^ Array of layers. group only.
+  , image            :: Maybe FilePath          -- ^ Image used by this layer. @imagelayer@ only.
+  , layers           :: Maybe (Vector Layer)    -- ^ Array of layers. @group@ only.
   , locked           :: Maybe Bool              -- ^ Whether layer is locked in the editor (default: false). (since Tiled 1.8.2)
   , name             :: Text                    -- ^ Name assigned to this layer
-  , objects          :: Maybe (Vector Object)   -- ^ Array of objects. objectgroup only.
+  , objects          :: Maybe (Vector Object)   -- ^ Array of objects. @objectgroup@ only.
   , offsetX          :: Maybe Double            -- ^ Horizontal layer offset in pixels (default: 0)
   , offsetY          :: Maybe Double            -- ^ Vertical layer offset in pixels (default: 0)
   , opacity          :: Double                  -- ^ Value between 0 and 1.
   , parallaxX        :: Maybe Double            -- ^ Horizontal parallax factor for this layer (default: 1).
   , parallaxY        :: Maybe Double            -- ^ Vertical parallax factor for this layer (default: 1).
   , properties       :: Maybe (Vector Property) -- ^ Array of Properties
-  , repeatX          :: Maybe Bool              -- ^ Whether the image drawn by this layer is repeated along the X axis. imagelayer only.
-  , repeatY          :: Maybe Bool              -- ^ Whether the image drawn by this layer is repeated along the Y axis. imagelayer only.
+  , repeatX          :: Maybe Bool              -- ^ Whether the image drawn by this layer is repeated along the X axis. @imagelayer@ only.
+  , repeatY          :: Maybe Bool              -- ^ Whether the image drawn by this layer is repeated along the Y axis. @imagelayer@ only.
   , startX           :: Maybe Int               -- ^ X coordinate where layer content starts (for infinite maps)
   , startY           :: Maybe Int               -- ^ Y coordinate where layer content starts (for infinite maps)
   , tintColor        :: Maybe Text              -- ^ Hex-formatted tint color (#RRGGBB or #AARRGGBB) that is multiplied with any graphics drawn by this layer or any child layers (optional).
-  , transparentColor :: Maybe Text              -- ^ Hex-formatted color (#RRGGBB) (optional). imagelayer only.
+  , transparentColor :: Maybe Text              -- ^ Hex-formatted color (#RRGGBB) (optional). @imagelayer@ only.
   , type_            :: Text                    -- ^ @tilelayer@, @objectgroup@, @imagelayer@ or @group@
   , visible          :: Bool                    -- ^ Whether layer is shown or hidden in editor
   , width            :: Maybe Int               -- ^ Column count. Same as map width for fixed-size maps.
@@ -48,3 +56,48 @@
 
 instance ToJSON Layer where
   toJSON = genericToJSON
+
+empty  :: Layer
+empty  = Layer
+  { chunks           = Nothing
+  , compression      = Nothing
+  , data_            = Nothing
+  , draworder        = Nothing
+  , encoding         = Nothing
+  , height           = Nothing
+  , id               = Nothing
+  , image            = Nothing
+  , layers           = Nothing
+  , locked           = Nothing
+  , name             = ""
+  , objects          = Nothing
+  , offsetX          = Nothing
+  , offsetY          = Nothing
+  , opacity          = 1.0
+  , parallaxX        = Nothing
+  , parallaxY        = Nothing
+  , properties       = Nothing
+  , repeatX          = Nothing
+  , repeatY          = Nothing
+  , startX           = Nothing
+  , startY           = Nothing
+  , tintColor        = Nothing
+  , transparentColor = Nothing
+  , type_            = ""
+  , visible          = True
+  , width            = Nothing
+  , x                = Nothing
+  , y                = Nothing
+  }
+
+pattern TILELAYER :: Text
+pattern TILELAYER = "tilelayer"
+
+pattern OBJECTGROUP :: Text
+pattern OBJECTGROUP = "objectgroup"
+
+pattern IMAGELAYER :: Text
+pattern IMAGELAYER = "imagelayer"
+
+pattern GROUP :: Text
+pattern GROUP = "group"
diff --git a/src/Codec/Tiled/Map.hs b/src/Codec/Tiled/Map.hs
--- a/src/Codec/Tiled/Map.hs
+++ b/src/Codec/Tiled/Map.hs
@@ -1,4 +1,11 @@
-module Codec.Tiled.Map where
+module Codec.Tiled.Map
+  ( Map(..)
+  , empty
+  , pattern ORTHOGONAL
+  , pattern ISOMETRIC
+  , pattern STAGGERED
+  , pattern HEXAGONAL
+  ) where
 
 import Codec.Tiled.Aeson (FromJSON(..), ToJSON(..), genericParseJSON, genericToJSON)
 import Data.Text (Text)
@@ -40,3 +47,41 @@
 
 instance ToJSON Map where
   toJSON = genericToJSON
+
+empty :: Map
+empty = Map
+    { backgroundColor  = Nothing
+    , compressionLevel = Nothing
+    , height           = 0
+    , hexSideLength    = Nothing
+    , infinite         = Nothing
+    , layers           = mempty
+    , nextLayerId      = 0
+    , nextObjectId     = 0
+    , orientation      = ""
+    , parallaxOriginX  = Nothing
+    , parallaxOriginY  = Nothing
+    , properties       = Nothing
+    , renderOrder      = Nothing
+    , staggerAxis      = Nothing
+    , staggerIndex     = Nothing
+    , tiledVersion     = ""
+    , tileHeight       = 0
+    , tilesets         = mempty
+    , tileWidth        = 0
+    , type_            = "map"
+    , version          = ""
+    , width            = 0
+    }
+
+pattern ORTHOGONAL :: Text
+pattern ORTHOGONAL = "orthogonal"
+
+pattern ISOMETRIC :: Text
+pattern ISOMETRIC = "isometric"
+
+pattern STAGGERED :: Text
+pattern STAGGERED = "staggered"
+
+pattern HEXAGONAL :: Text
+pattern HEXAGONAL = "hexagonal"
diff --git a/src/Codec/Tiled/Object/Text.hs b/src/Codec/Tiled/Object/Text.hs
--- a/src/Codec/Tiled/Object/Text.hs
+++ b/src/Codec/Tiled/Object/Text.hs
@@ -1,4 +1,7 @@
-module Codec.Tiled.Object.Text where
+module Codec.Tiled.Object.Text
+  ( Text(..)
+  , empty
+  ) where
 
 import Data.Text qualified as The
 import GHC.Generics (Generic)
@@ -26,3 +29,19 @@
 
 instance ToJSON Text where
   toJSON = genericToJSON
+
+empty :: Text
+empty = Text
+  { bold       = Nothing
+  , color      = Nothing
+  , fontFamily = Nothing
+  , hAlign     = Nothing
+  , italic     = Nothing
+  , kerning    = Nothing
+  , pixelSize  = Nothing
+  , strikeout  = Nothing
+  , text       = ""
+  , underline  = Nothing
+  , vAlign     = Nothing
+  , wrap       = Nothing
+  }
diff --git a/src/Codec/Tiled/Tileset.hs b/src/Codec/Tiled/Tileset.hs
--- a/src/Codec/Tiled/Tileset.hs
+++ b/src/Codec/Tiled/Tileset.hs
@@ -1,4 +1,7 @@
-module Codec.Tiled.Tileset where
+module Codec.Tiled.Tileset
+  ( Tileset(..)
+  , empty
+  ) where
 
 import Data.Text (Text)
 import Data.Vector (Vector)
@@ -48,3 +51,32 @@
 
 instance ToJSON Tileset where
   toJSON = genericToJSON
+
+empty :: Tileset
+empty =  Tileset
+  { backgroundColor  = Nothing
+  , columns          = 0
+  , firstGid         = Nothing
+  , grid             = Nothing
+  , image            = ""
+  , imageHeight      = 0
+  , imageWidth       = 0
+  , margin           = 0
+  , name             = ""
+  , objectAlignment  = Nothing
+  , properties       = Nothing
+  , source           = Nothing
+  , spacing          = 0
+  , terrains         = Nothing
+  , tileCount        = 0
+  , tiledVersion     = Nothing
+  , tileHeight       = 0
+  , tileOffset       = Nothing
+  , tiles            = Nothing
+  , tileWidth        = 0
+  , transformations  = Nothing
+  , transparentColor = Nothing
+  , type_            = Nothing
+  , version          = Nothing
+  , wangSets         = Nothing
+  }
diff --git a/src/Codec/Tiled/Tileset/Ref.hs b/src/Codec/Tiled/Tileset/Ref.hs
--- a/src/Codec/Tiled/Tileset/Ref.hs
+++ b/src/Codec/Tiled/Tileset/Ref.hs
@@ -43,6 +43,6 @@
       case toJSON embedded of
         Aeson.Object o ->
           Aeson.Object $
-            KeyMap.insert "firstGid" (toJSON firstGid) o
+            KeyMap.insert "firstgid" (toJSON firstGid) o
         _nonObject ->
           error "assert: TilesetRef is Object"
diff --git a/src/Codec/Tiled/Tileset/Tile.hs b/src/Codec/Tiled/Tileset/Tile.hs
--- a/src/Codec/Tiled/Tileset/Tile.hs
+++ b/src/Codec/Tiled/Tileset/Tile.hs
@@ -1,4 +1,7 @@
-module Codec.Tiled.Tileset.Tile where
+module Codec.Tiled.Tileset.Tile
+  ( Tile(..)
+  , empty
+  ) where
 
 import Data.Text (Text)
 import Data.Vector (Vector)
@@ -28,3 +31,17 @@
 
 instance ToJSON Tile where
   toJSON = genericToJSON
+
+empty :: Tile
+empty = Tile
+  { animation   = Nothing
+  , id          = 0
+  , image       = Nothing
+  , imageHeight = 0
+  , imageWidth  = 0
+  , objectGroup = Nothing
+  , probability = Nothing
+  , properties  = Nothing
+  , terrain     = Nothing
+  , type_       = Nothing
+  }
diff --git a/src/Codec/Tiled/Tileset/Transformations.hs b/src/Codec/Tiled/Tileset/Transformations.hs
--- a/src/Codec/Tiled/Tileset/Transformations.hs
+++ b/src/Codec/Tiled/Tileset/Transformations.hs
@@ -1,4 +1,7 @@
-module Codec.Tiled.Tileset.Transformations where
+module Codec.Tiled.Tileset.Transformations
+  ( Transformations(..)
+  , empty
+  ) where
 
 import GHC.Generics (Generic)
 
@@ -17,3 +20,11 @@
 
 instance ToJSON Transformations where
   toJSON = genericToJSON
+
+empty :: Transformations
+empty = Transformations
+  { hFlip               = Nothing
+  , vFlip               = Nothing
+  , rotate              = Nothing
+  , preferUntransformed = Nothing
+  }
diff --git a/src/Codec/Tiled/World.hs b/src/Codec/Tiled/World.hs
--- a/src/Codec/Tiled/World.hs
+++ b/src/Codec/Tiled/World.hs
@@ -1,4 +1,7 @@
-module Codec.Tiled.World where
+module Codec.Tiled.World
+  ( World(..)
+  , empty
+  ) where
 
 import Data.Aeson (FromJSON(..), ToJSON(..), genericParseJSON, genericToJSON)
 import Data.Text (Text)
@@ -22,3 +25,11 @@
 
 instance ToJSON World where
   toJSON = genericToJSON (mkOptions remapFields_)
+
+empty :: World
+empty = World
+  { maps                 = Nothing
+  , patterns             = Nothing
+  , type_                = Nothing
+  , onlyShowAdjacentMaps = Nothing
+  }
