diff --git a/geode.cabal b/geode.cabal
index 030f41e311130398eb2a706963a5e30bb94ebe4d..cab450a8ffde587f953c035c31536412160ed9f1 100644
--- a/geode.cabal
+++ b/geode.cabal
@@ -35,7 +35,8 @@ library
 
     -- LANGUAGE extensions used by modules in this package.
     -- other-extensions:
-    build-depends:    base >=4.16 && <4.17
+    build-depends:    aeson >= 2.0.3.0 && <2.1
+                    , base >=4.16 && <4.17
                     , bytestring >= 0.11.3 && <0.12
                     , containers >= 0.6.5.1 && <0.7
                     , cassava >= 0.5.3 && <0.6
diff --git a/guix.scm b/guix.scm
index 26f2204f9f30b349f1881f295fd32589d0e5288e..e3b1f959ba6d061a4163f6bc3571e7f20021d038 100644
--- a/guix.scm
+++ b/guix.scm
@@ -1,6 +1,7 @@
 (use-modules ((gnu packages haskell-xyz) #:select (ghc-cassava
                                                    ghc-optparse-applicative))
              ((gnu packages haskell-check) #:select (ghc-hunit))
+             ((gnu packages haskell-web) #:select (ghc-aeson))
              ((guix build-system haskell) #:select (haskell-build-system))
              ((guix git-download) #:select (git-predicate))
              ((guix gexp) #:select (local-file))
@@ -17,7 +18,7 @@
           #:recursive? #t
           #:select? (git-predicate %source-dir)))
     (build-system haskell-build-system)
-    (inputs (list ghc-cassava ghc-optparse-applicative ghc-hunit))
+    (inputs (list ghc-aeson ghc-cassava ghc-optparse-applicative ghc-hunit))
     (home-page "https://gitlab.liris.cnrs.fr/geode/ghc-geode")
     (synopsis "Data structures and tooling used in project GEODE")
     (description
diff --git a/lib/GEODE/Metadata/PrimaryKey.hs b/lib/GEODE/Metadata/PrimaryKey.hs
index 037c4a5d126149179f058a87a14bbcd6102d2961..393db90b8ff2b33cd48499d2cbd2d5f6ca710df2 100644
--- a/lib/GEODE/Metadata/PrimaryKey.hs
+++ b/lib/GEODE/Metadata/PrimaryKey.hs
@@ -5,6 +5,7 @@ module GEODE.Metadata.PrimaryKey
   , relativePath
   , uid ) where
 
+import Data.Aeson (ToJSON(..))
 import Data.Csv (FromField(..), FromNamedRecord(..), ToNamedRecord(..), ToField(..))
 import GEODE.Metadata.Types (Has(..))
 import GEODE.Metadata.TSV.Header (DefaultFields(..), HasDefaultHeader(..))
@@ -23,6 +24,9 @@ instance FromField Book where
 instance ToField Book where
   toField = toField . show
 
+instance ToJSON Book where
+  toJSON = toJSON . show
+
 data PrimaryKey = PrimaryKey
   { book :: Book
   , tome :: Int