diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Revision history for taskwarrior
 
+## 0.3.0.0
+
+* Only export `id` and `urgency` when non default.
+* Change use of `[]` to `Set` because that matches the semantic better.
+
 ## 0.2.1.0
 
 * Add helpers for onAdd and onModify hooks.
diff --git a/src/Taskwarrior/IO.hs b/src/Taskwarrior/IO.hs
--- a/src/Taskwarrior/IO.hs
+++ b/src/Taskwarrior/IO.hs
@@ -116,7 +116,7 @@
 
 readTaskLine :: String -> IO Task
 readTaskLine errorMsg =
-  maybe (fail errorMsg) pure =<< Aeson.decode' . LBS.fromStrict <$> BS.getLine
+  maybe (fail errorMsg) pure . Aeson.decode' . LBS.fromStrict =<< BS.getLine
 
 -- | Like onModifyPure but for the onAdd hook.
 onAddPure :: (Task -> Task) -> IO ()
diff --git a/src/Taskwarrior/Task.hs b/src/Taskwarrior/Task.hs
--- a/src/Taskwarrior/Task.hs
+++ b/src/Taskwarrior/Task.hs
@@ -51,6 +51,8 @@
 import           Taskwarrior.Annotation         ( Annotation )
 import qualified Taskwarrior.Time              as Time
 import qualified Data.HashMap.Strict           as HashMap
+import           Data.Set                       ( Set )
+import qualified Data.Set                      as Set
 import           Foreign.Marshal.Utils          ( fromBool )
 
 -- | A 'Task' represents a task from taskwarrior.
@@ -72,12 +74,12 @@
         modified       :: Maybe UTCTime,
         due            :: Maybe UTCTime,
         until          :: Maybe UTCTime,
-        annotations    :: [Annotation],
+        annotations    :: Set Annotation,
         scheduled      :: Maybe UTCTime,
         project        :: Maybe Text,
         priority       :: Maybe Priority,
-        depends        :: [UUID],
-        tags           :: [Tag],
+        depends        :: Set UUID,
+        tags           :: Set Tag,
         urgency        :: Double,
         uda            :: UDA
 } deriving (Eq, Show, Read)
@@ -132,7 +134,9 @@
     project     <- object .:? "project"
     priority    <- join
       <$> parseFromFieldWithMay Priority.parseMay object "priority"
-    depends <- maybe (pure []) parseUuidList (HashMap.lookup "depends" object)
+    depends <- maybe (pure mempty)
+                     parseUuidList
+                     (HashMap.lookup "depends" object)
     tags    <- Foldable.fold <$> object .:? "tags"
     urgency <- fromMaybe 0 <$> object .:? "urgency"
     pure Task { until = until_, .. }
@@ -145,22 +149,24 @@
 parseFromFieldWithMay parser object name =
   traverse parser (HashMap.lookup name object)
 
-parseUuidList :: Aeson.Value -> Aeson.Types.Parser [UUID]
+parseUuidList :: Aeson.Value -> Aeson.Types.Parser (Set UUID)
 parseUuidList =
-  withText "Text" $ mapM (parseJSON . Aeson.String) . Text.splitOn ","
+  withText "Text"
+    $ fmap Set.fromList
+    . mapM (parseJSON . Aeson.String)
+    . Text.splitOn ","
 
 instance ToJSON Task where
   toJSON Task { until = until_, ..} =
     Aeson.object
       $  Status.toPairs status
       <> [ "uuid" .= uuid
-         , "id" .= fromMaybe 0 id
          , "entry" .= Time.toValue entry
          , "description" .= description
-         , "urgency" .= urgency
          ]
+      <> [ "urgency" .= urgency | urgency /= 0 ]
       <> maybe [] RecurringChild.toPairs recurringChild
-      <> ifNotNullList annotations ("annotations" .=)
+      <> ifNotNullSet annotations ("annotations" .=)
       <> Maybe.mapMaybe
            (\(name, value) -> (name .=) . Time.toValue <$> value)
            [ ("start"    , start)
@@ -170,17 +176,25 @@
            , ("until"    , until_)
            ]
       <> Maybe.catMaybes
-           [("project" .=) <$> project, ("priority" .=) <$> priority]
-      <> ifNotNullList
+           [ ("id" .=) <$> id
+           , ("project" .=) <$> project
+           , ("priority" .=) <$> priority
+           ]
+      <> ifNotNullSet
            depends
-           (("depends" .=) . Text.intercalate "," . fmap UUID.toText)
-      <> ifNotNullList tags ("tags" .=)
+           ( ("depends" .=)
+           . Text.intercalate ","
+           . fmap UUID.toText
+           . Set.toList
+           )
+      <> ifNotNullSet tags ("tags" .=)
       <> HashMap.toList uda
 
-ifNotNullList :: [b] -> ([b] -> a) -> [a]
-ifNotNullList list f =
-  (Semigroup.stimesMonoid . (fromBool :: Bool -> Integer) . not . null $ list)
-    [f list]
+ifNotNullSet :: (Ord b) => Set b -> (Set b -> a) -> [a]
+ifNotNullSet set f =
+  (Semigroup.stimesMonoid . (fromBool :: Bool -> Integer) . not . Set.null $ set
+    )
+    [f set]
 
 -- | Makes a Task with the given mandatory fields uuid, entry time and description. See createTask for a non-pure version which needs less parameters.
 makeTask :: UUID -> UTCTime -> Text -> Task
@@ -197,9 +211,9 @@
                                        , start          = Nothing
                                        , scheduled      = Nothing
                                        , until          = Nothing
-                                       , annotations    = []
-                                       , depends        = []
-                                       , tags           = []
+                                       , annotations    = mempty
+                                       , depends        = mempty
+                                       , tags           = mempty
                                        , urgency        = 0
                                        , uda            = HashMap.empty
                                        }
diff --git a/taskwarrior.cabal b/taskwarrior.cabal
--- a/taskwarrior.cabal
+++ b/taskwarrior.cabal
@@ -4,7 +4,7 @@
 -- PVP summary:     +-+------- breaking API changes
 --                  | | +----- non-breaking API additions
 --                  | | | +--- code changes with no API change
-version: 0.2.1.0
+version: 0.3.0.0
 synopsis:           Types and aeson instances for taskwarrior tasks
 description:
   Types and aeson instances for the https://taskwarrior.org task import/export feature
@@ -46,8 +46,9 @@
 
   build-depends:
     , aeson                 ^>=1.4.2.0
-    , base                  >=4.11     && <4.14
+    , base                  >=4.11     && <4.15
     , bytestring            ^>=0.10.8.2
+    , containers            >=0.5.0.0  && <0.7
     , process               ^>=1.6.5.0
     , random                ^>=1.1
     , text                  ^>=1.2.3.0
