diff --git a/gopro-plus.cabal b/gopro-plus.cabal
--- a/gopro-plus.cabal
+++ b/gopro-plus.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 5b7fb7002e78e23ecd379959812b6b7c768dd92c34f4c9209fb38f4fb3b6bf65
+-- hash: 28577c1446cea69369980bb3681d24a71ca38ae9c295c29333f0e6671cff1972
 
 name:           gopro-plus
-version:        0.4.1.1
+version:        0.4.1.2
 synopsis:       GoPro Plus Client API.
 description:    Please see the README on GitHub at <https://github.com/dustin/gopro-plus#readme>
 category:       Web
@@ -74,6 +74,7 @@
   ghc-options: -threaded -rtsopts -with-rtsopts=-N
   build-depends:
       HUnit
+    , QuickCheck
     , aeson
     , base >=4.7 && <5
     , bytestring
@@ -81,6 +82,7 @@
     , exceptions
     , filepath
     , generic-deriving
+    , generic-random
     , gopro-plus
     , lens
     , lens-aeson
diff --git a/src/GoPro/Plus/Media.hs b/src/GoPro/Plus/Media.hs
--- a/src/GoPro/Plus/Media.hs
+++ b/src/GoPro/Plus/Media.hs
@@ -43,11 +43,11 @@
   updateMedium, putMedium
   ) where
 
-import           Control.Lens
+import           Control.Lens                 hiding ((.=))
 import           Control.Monad.IO.Class       (MonadIO (..))
 import           Data.Aeson                   (FromJSON (..), Options (..), ToJSON (..), Value (..), defaultOptions,
                                                fieldLabelModifier, genericParseJSON, genericToEncoding, genericToJSON,
-                                               (.:))
+                                               object, (.:), (.=))
 import qualified Data.Aeson                   as J
 import           Data.Aeson.Types             (typeMismatch)
 import qualified Data.ByteString.Lazy         as BL
@@ -218,7 +218,7 @@
     , _file_head            :: String
     , _file_url             :: String
     }
-    deriving (Generic, Show)
+    deriving (Generic, Eq, Show)
 
 makeLenses  ''File
 
@@ -230,6 +230,10 @@
     fieldLabelModifier = dropPrefix "_file_"
     }
 
+instance ToJSON File where
+  toEncoding = genericToEncoding jsonOpts{ fieldLabelModifier = dropPrefix "_file_" }
+  toJSON = genericToJSON jsonOpts{ fieldLabelModifier = dropPrefix "_file_" }
+
 data Variation = Variation
     { _var_height     :: Int
     , _var_width      :: Int
@@ -240,7 +244,7 @@
     , _var_head       :: String
     , _var_url        :: String
     }
-    deriving (Generic, Show)
+    deriving (Generic, Eq, Show)
 
 makeLenses ''Variation
 
@@ -254,12 +258,16 @@
   fieldLabelModifier = dropPrefix "_var_"
   }
 
+instance ToJSON Variation where
+  toEncoding = genericToEncoding jsonOpts{ fieldLabelModifier = dropPrefix "_var_" }
+  toJSON = genericToJSON jsonOpts{ fieldLabelModifier = dropPrefix "_var_" }
+
 data SpriteFrame = SpriteFrame
     { _frame_count  :: Int
     , _frame_height :: Int
     , _frame_width  :: Int
     }
-    deriving (Generic, Show)
+    deriving (Generic, Eq, Show)
 
 makeLenses ''SpriteFrame
 
@@ -268,6 +276,10 @@
     fieldLabelModifier = dropPrefix "_frame_"
   }
 
+instance ToJSON SpriteFrame where
+  toEncoding = genericToEncoding jsonOpts{ fieldLabelModifier = dropPrefix "_frame_" }
+  toJSON = genericToJSON jsonOpts{ fieldLabelModifier = dropPrefix "_frame_" }
+
 data Sprite = Sprite
     { _sprite_fps    :: Double
     , _sprite_frame  :: SpriteFrame
@@ -277,7 +289,7 @@
     , _sprite_heads  :: [String]
     , _sprite_urls   :: [String]
     }
-    deriving (Generic, Show)
+    deriving (Generic, Eq, Show)
 
 makeLenses ''Sprite
 
@@ -286,13 +298,17 @@
     fieldLabelModifier = dropPrefix "_sprite_"
   }
 
+instance ToJSON Sprite where
+  toEncoding = genericToEncoding jsonOpts{ fieldLabelModifier = dropPrefix "_sprite_" }
+  toJSON = genericToJSON jsonOpts{ fieldLabelModifier = dropPrefix "_sprite_" }
+
 data SidecarFile = SidecarFile
   { _sidecar_fps   :: Double
   , _sidecar_label :: String
   , _sidecar_type  :: String
   , _sidecar_head  :: String
   , _sidecar_url   :: String
-  } deriving (Generic, Show)
+  } deriving (Generic, Eq, Show)
 
 makeLenses ''SidecarFile
 
@@ -306,24 +322,32 @@
     fieldLabelModifier = dropPrefix "_sidecar_"
   }
 
+instance ToJSON SidecarFile where
+  toEncoding = genericToEncoding jsonOpts{ fieldLabelModifier = dropPrefix "_sidecar_" }
+  toJSON = genericToJSON jsonOpts{ fieldLabelModifier = dropPrefix "_sidecar_" }
+
 data FileStuff = FileStuff
     { _files         :: [File]
     , _variations    :: [Variation]
     , _sprites       :: [Sprite]
     , _sidecar_files :: [SidecarFile]
     }
-    deriving (Generic, Show)
+    deriving (Generic, Eq, Show)
 
 makeLenses ''FileStuff
 
 instance FromJSON FileStuff where
   parseJSON = genericParseJSON jsonOpts
 
+instance ToJSON FileStuff where
+  toEncoding = genericToEncoding jsonOpts{ fieldLabelModifier = dropPrefix "_" }
+  toJSON = genericToJSON jsonOpts{ fieldLabelModifier = dropPrefix "_" }
+
 data FileInfo = FileInfo
     { _fileStuff :: FileStuff
     , _filename  :: String
     }
-    deriving (Generic, Show)
+    deriving (Generic, Eq, Show)
 
 makeLenses ''FileInfo
 
@@ -333,6 +357,9 @@
     fs <- parseJSON o
     FileInfo fs <$> v .: "filename"
   parseJSON invalid    = typeMismatch "Response" invalid
+
+instance ToJSON FileInfo where
+  toJSON FileInfo{..} = object ["_embedded" .= _fileStuff, "filename" .= _filename]
 
 dlURL :: MediumID -> String
 dlURL k = "https://api.gopro.com/media/" <> T.unpack k <> "/download"
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -3,8 +3,11 @@
 import           Control.Lens
 import qualified Data.Aeson            as J
 import qualified Data.ByteString.Lazy  as BL
+import           Data.Maybe            (fromJust)
 import           Text.RawString.QQ     (r)
 
+import           Generic.Random        (genericArbitrary, uniform)
+import           Test.QuickCheck       ((===))
 import           Test.Tasty
 import           Test.Tasty.HUnit
 import           Test.Tasty.QuickCheck as QC
@@ -50,11 +53,28 @@
 
   assertEqual (show fs) "intoalightpost" (fs ^. files . folded . file_transforms . folded . folded)
 
+instance Arbitrary FileInfo where arbitrary = genericArbitrary uniform
 
+instance Arbitrary FileStuff where arbitrary = genericArbitrary uniform
+
+instance Arbitrary Variation where arbitrary = genericArbitrary uniform
+
+instance Arbitrary SpriteFrame where arbitrary = genericArbitrary uniform
+
+instance Arbitrary SidecarFile where arbitrary = genericArbitrary uniform
+
+instance Arbitrary Sprite where arbitrary = genericArbitrary uniform
+
+instance Arbitrary File where arbitrary = genericArbitrary uniform
+
+propRoundtripFileInfo :: FileInfo -> Property
+propRoundtripFileInfo = fromJust . J.decode . J.encode >>= (===)
+
 tests :: [TestTree]
 tests = [
     testCase "Parsing" testSearchParser,
-    testCase "FileInfo" testFileInfo
+    testCase "FileInfo" testFileInfo,
+    testProperty "FileInfo round tripping" propRoundtripFileInfo
     ]
 
 main :: IO ()
