diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+* 0.5
+
+  - no 'Dot' and 'matrix-market' support for now: 
+    Dot/graphviz export is already supported within algebraic-graphs and matrix-market can be made available on a need basis
+    
+  - add JSON codec
+  
+  - add 'serialise'-based binary codec
+
 * 0.4
 
   LINQS datasets : 
diff --git a/algebraic-graphs-io.cabal b/algebraic-graphs-io.cabal
--- a/algebraic-graphs-io.cabal
+++ b/algebraic-graphs-io.cabal
@@ -1,5 +1,5 @@
 name:                algebraic-graphs-io
-version:             0.4
+version:             0.5
 synopsis:            I/O utilities and datasets for algebraic-graphs
 description:         I/O utilities and datasets for algebraic-graphs. See README for details
 homepage:            https://github.com/ocramz/algebraic-graphs-io
@@ -19,24 +19,25 @@
                      assets/simulated_blockmodel_graph_50_nodes_truePartition.tsv
                      assets/simulated_blockmodel_graph_50_nodes.tsv
 cabal-version:       >=1.10
-tested-with:         GHC == 8.8.4
+tested-with:         GHC == 8.8.4, GHC == 9.0.2
 
 library
   default-language:    Haskell2010
   ghc-options:         -Wall
   hs-source-dirs:      src
   exposed-modules:     Algebra.Graph.IO.GML
-                       Algebra.Graph.IO.Dot
                        Algebra.Graph.IO.Datasets
                        Algebra.Graph.IO.Datasets.LINQS
                        Algebra.Graph.IO.Datasets.LINQS.Citeseer
                        Algebra.Graph.IO.Datasets.LINQS.Cora
-                       Algebra.Graph.IO.MatrixMarket
+                       Algebra.Graph.IO.JSON
+                       Algebra.Graph.IO.Serialise
                        Algebra.Graph.IO.SV
-                       Algebra.Graph.IO.Internal.Conduit
+                       Algebra.Graph.IO.Internal
+  other-modules:       Algebra.Graph.IO.Internal.Conduit
                        Algebra.Graph.IO.Internal.Megaparsec
-  other-modules:       
-  build-depends:       algebraic-graphs
+  build-depends:       aeson
+                     , algebraic-graphs
                      , attoparsec
                      , base >= 4.7 && < 5
                      , binary
@@ -47,15 +48,14 @@
                      , containers
                      , csv-conduit
                      , directory
-                     , dot
                      , exceptions
                      , filepath
                      , http-conduit
-                     , matrix-market-attoparsec
                      , megaparsec
                      , mtl
                      , parser-combinators
                      , primitive
+                     , serialise
                      , tar-conduit
                      , text
                      , transformers
@@ -68,9 +68,11 @@
   hs-source-dirs:      test
   main-is:             Spec.hs
   build-depends:       base
+                     , aeson
+                     , algebraic-graphs
                      , algebraic-graphs-io
                      , hspec
-                     , QuickCheck
+                     , serialise
 
 source-repository head
   type:     git
diff --git a/src/Algebra/Graph/IO/Datasets/LINQS.hs b/src/Algebra/Graph/IO/Datasets/LINQS.hs
--- a/src/Algebra/Graph/IO/Datasets/LINQS.hs
+++ b/src/Algebra/Graph/IO/Datasets/LINQS.hs
@@ -56,14 +56,11 @@
 -- tar-conduit
 import Data.Conduit.Tar (Header(..), untarChunks, TarChunk, withEntries, FileInfo, filePath, withFileInfo, headerFileType, FileType(..), headerFilePath)
 -- text
-
 import qualified Data.Text as T (Text, unwords)
 
--- transformers
 
 
-import Algebra.Graph.IO.Internal.Conduit (fetch, unTarGz)
-import Algebra.Graph.IO.Internal.Megaparsec (Parser, ParserT, ParseE, symbol, lexeme, alphaNum)
+import Algebra.Graph.IO.Internal (fetch, unTarGz, Parser, ParserT, ParseE, symbol, lexeme, alphaNum)
 import Algebra.Graph.IO.SV (parseTSV)
 
 {-
diff --git a/src/Algebra/Graph/IO/Dot.hs b/src/Algebra/Graph/IO/Dot.hs
deleted file mode 100644
--- a/src/Algebra/Graph/IO/Dot.hs
+++ /dev/null
@@ -1,29 +0,0 @@
-{-# language OverloadedStrings #-}
-{-# options_ghc -Wno-unused-imports #-}
-module Algebra.Graph.IO.Dot where
-
-import Dot (DotGraph(..), Strictness(..), Directionality(..), Statement(..), Element(..), NodeStatement(..), EdgeStatement(..), Attribute(..), Id(..))
-
-
-{-
-main :: IO ()
-main = do
-  putStrLn $ "dumping example dotgraph to " ++ target
-  encodeToFile target example
- 
-target :: FilePath
-target = "example/example.dot"
-
-example :: DotGraph
-example = DotGraph Strict Directed (Just "foobar")
-  [ StatementNode $ NodeStatement "a1"
-    [ Attribute "color" "blue"
-    , Attribute "shape" "box"
-    ]
-  , StatementNode $ NodeStatement "a2" []
-  , StatementEdge $ EdgeStatement (ListTwo "a1" "a2" ["a3"])
-      [ Attribute "color" "red"
-      ]
-  ]
-
--}
diff --git a/src/Algebra/Graph/IO/Internal.hs b/src/Algebra/Graph/IO/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Algebra/Graph/IO/Internal.hs
@@ -0,0 +1,7 @@
+module Algebra.Graph.IO.Internal (
+  module Algebra.Graph.IO.Internal.Conduit,
+  module Algebra.Graph.IO.Internal.Megaparsec
+                                 ) where
+
+import Algebra.Graph.IO.Internal.Conduit
+import Algebra.Graph.IO.Internal.Megaparsec
diff --git a/src/Algebra/Graph/IO/JSON.hs b/src/Algebra/Graph/IO/JSON.hs
new file mode 100644
--- /dev/null
+++ b/src/Algebra/Graph/IO/JSON.hs
@@ -0,0 +1,135 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# language OverloadedStrings #-}
+{-# options_ghc -Wno-unused-imports #-}
+{-|
+Module      : Algebra.Graph.IO.JSON
+Description : 'aeson' instances for algebraic-graphs types
+Copyright   : (c) Marco Zocca, 2022
+Maintainer  : ocramz
+Stability   : experimental
+Portability : POSIX
+
+Orphan instances for compatibility between 'algebraic-graphs' and 'aeson'.
+
+Import only if you know what you're doing.
+-}
+module Algebra.Graph.IO.JSON () where
+
+import Control.Applicative (Alternative(..))
+import GHC.Generics (Generic)
+
+-- aeson
+import qualified Data.Aeson as A (FromJSON(..), ToJSON(..), encode, eitherDecode, Value, withArray, withText, withObject, (.:), Object)
+import qualified Data.Aeson.Types as A (Parser)
+import qualified Data.Aeson.Encoding as A (value, fromEncoding)
+-- alga
+import qualified Algebra.Graph as G (Graph(..), edges, foldg)
+import qualified Algebra.Graph.Labelled as GL (Graph(..), edges, foldg)
+
+-- unlabeled edges
+
+instance A.ToJSON a => A.ToJSON (G.Graph a) where
+  toJSON = graphToValue
+
+
+graphToValue :: (A.ToJSON t) =>
+                G.Graph t -> A.Value
+graphToValue = go
+  where
+    go G.Empty = A.toJSON Empty
+    go (G.Vertex x) = A.toJSON (Vertex x)
+    go (G.Overlay x y) = A.toJSON (Overlay (go x) (go y))
+    go (G.Connect x y) = A.toJSON (Connect (go x) (go y))
+
+
+
+
+instance A.FromJSON a => A.FromJSON (G.Graph a) where
+  parseJSON x = A.withObject "Graph" gObj x <|>
+                parseE x
+
+gObj :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)
+gObj o = parseC o <|>
+         parseO o <|>
+         parseV o
+
+parseE :: A.Value -> A.Parser (G.Graph a)
+parseE = A.withArray "empty" $ \t -> if null t then pure G.Empty else fail "cannot parse Empty"
+
+parseV :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)
+parseV o = G.Vertex <$> o A..: "v"
+
+parseO :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)
+parseO o = do
+  a <- o A..: "o1"
+  b <- o A..: "o2"
+  pure $ G.Overlay a b
+
+parseC :: A.FromJSON a => A.Object -> A.Parser (G.Graph a)
+parseC o = do
+  a <- o A..: "c1"
+  b <- o A..: "c2"
+  pure $ G.Connect a b
+
+
+
+
+instance (A.ToJSON a, A.ToJSON e) => A.ToJSON (GL.Graph e a) where
+  toJSON = graphLToValue
+
+graphLToValue :: (A.ToJSON a, A.ToJSON e) => GL.Graph e a -> A.Value
+graphLToValue = go
+  where
+    go GL.Empty = A.toJSON Empty
+    go (GL.Vertex x) = A.toJSON (Vertex x)
+    go (GL.Connect e x y) = A.toJSON (LEdge e (go x) (go y))
+
+
+instance (A.FromJSON e, A.FromJSON a) => A.FromJSON (GL.Graph e a) where
+  parseJSON x = A.withObject "Graph (labeled)" gLObj x <|>
+                parseEL x
+
+gLObj :: (A.FromJSON e, A.FromJSON a) => A.Object -> A.Parser (GL.Graph e a)
+gLObj o = parseCL o <|>
+          parseVL o
+
+parseEL :: A.Value -> A.Parser (GL.Graph e a)
+parseEL = A.withArray "empty" $ \t -> if null t then pure GL.Empty else fail "cannot parse Empty"
+
+parseVL :: A.FromJSON a => A.Object -> A.Parser (GL.Graph e a)
+parseVL o = GL.Vertex <$> o A..: "v"
+
+parseCL :: (A.FromJSON e, A.FromJSON a) =>
+           A.Object -> A.Parser (GL.Graph e a)
+parseCL o = do
+  e <- o A..: "l"
+  a <- o A..: "e1"
+  b <- o A..: "e2"
+  pure $ GL.Connect e a b
+
+
+-- | Helper types
+
+-- empty
+data Empty = Empty deriving (Eq, Show, Generic)
+instance A.ToJSON Empty
+-- vertex
+newtype Vertex a = Vertex { v :: a } deriving (Eq, Show, Generic)
+instance A.ToJSON a => A.ToJSON (Vertex a)
+
+-- overlay
+data Overlay a = Overlay { o1 :: a, o2 :: a} deriving (Eq, Show, Generic)
+instance A.ToJSON a => A.ToJSON (Overlay a)
+
+-- connect
+data Connect a = Connect { c1 :: a, c2 :: a} deriving (Eq, Show, Generic)
+instance A.ToJSON a => A.ToJSON (Connect a)
+
+
+
+
+data LEdge e a = LEdge { l :: e, e1 :: a, e2 :: a } deriving (Eq, Show, Generic)
+instance (A.ToJSON e, A.ToJSON a) => A.ToJSON (LEdge e a)
+
diff --git a/src/Algebra/Graph/IO/MatrixMarket.hs b/src/Algebra/Graph/IO/MatrixMarket.hs
deleted file mode 100644
--- a/src/Algebra/Graph/IO/MatrixMarket.hs
+++ /dev/null
@@ -1,4 +0,0 @@
-{-# options_ghc -Wno-unused-imports #-}
-module Algebra.Graph.IO.MatrixMarket where
-
-import Data.Matrix.MatrixMarket (Matrix(..), readMatrix', nnz, dim, numDat, Array(..), readArray', dimArr, numDatArr, Structure(..), ImportError(..))
diff --git a/src/Algebra/Graph/IO/Serialise.hs b/src/Algebra/Graph/IO/Serialise.hs
new file mode 100644
--- /dev/null
+++ b/src/Algebra/Graph/IO/Serialise.hs
@@ -0,0 +1,68 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE LambdaCase #-}
+{-|
+Module      : Algebra.Graph.IO.Serialise
+Description : 'serialise' instances for algebraic-graphs types
+Copyright   : (c) Marco Zocca, 2022
+Maintainer  : ocramz
+Stability   : experimental
+Portability : POSIX
+
+Orphan instances for compatibility between 'algebraic-graphs' and 'serialise'.
+
+Import only if you know what you're doing.
+-}
+module Algebra.Graph.IO.Serialise () where
+
+-- alga
+import qualified Algebra.Graph as G (Graph(..), edges, foldg)
+import qualified Algebra.Graph.Labelled as GL (Graph(..), edges, foldg)
+-- serialise
+import qualified Codec.Serialise as CS (Serialise(..), serialise, serialiseIncremental, deserialiseOrFail, DeserialiseFailure)
+import qualified Codec.Serialise.Encoding as CS (encodeListLen, encodeListLenIndef, encodeWord)
+import qualified Codec.Serialise.Decoding as CS (decodeListLen, decodeListLenIndef, decodeWord)
+
+
+instance CS.Serialise a => CS.Serialise (G.Graph a) where
+  encode = \case
+    G.Empty -> CS.encodeListLen 1 <> CS.encodeWord 0
+    G.Vertex x -> CS.encodeListLen 2 <> CS.encodeWord 1 <> CS.encode x
+    G.Overlay a b -> CS.encodeListLen 3 <> CS.encodeWord 2 <> CS.encode a <> CS.encode b
+    G.Connect a b -> CS.encodeListLen 3 <> CS.encodeWord 3 <> CS.encode a <> CS.encode b
+  decode = do
+    n <- CS.decodeListLen
+    t <- CS.decodeWord -- constructor tag
+    case (t, n) of
+      (0, 1) -> pure $ G.Empty
+      (1, 2) -> do
+        !x <- CS.decode
+        pure $ G.Vertex x
+      (2, 3) -> do
+        !x <- CS.decode
+        !y <- CS.decode
+        pure $ G.Overlay x y
+      (3, 3) -> do
+        !x <- CS.decode
+        !y <- CS.decode
+        pure $ G.Connect x y
+      e -> fail $ unwords ["unknown tag", show e]
+
+instance (CS.Serialise e, CS.Serialise a) => CS.Serialise (GL.Graph e a) where
+  encode = \case
+    GL.Empty -> CS.encodeListLen 1 <> CS.encodeWord 0
+    GL.Vertex x -> CS.encodeListLen 2 <> CS.encodeWord 1 <> CS.encode x
+    GL.Connect e a b -> CS.encodeListLen 4 <> CS.encodeWord 2 <> CS.encode e <> CS.encode a <> CS.encode b
+  decode = do
+    n <- CS.decodeListLen
+    t <- CS.decodeWord -- constructor tag
+    case (t, n) of
+      (0, 1) -> pure $ GL.Empty
+      (1, 2) -> do
+        !x <- CS.decode
+        pure $ GL.Vertex x
+      (2, 4) -> do
+        !e <- CS.decode
+        !x <- CS.decode
+        !y <- CS.decode
+        pure $ GL.Connect e x y
+      e -> fail $ unwords ["unknown tag", show e]
