diff --git a/swh/model/model.py b/swh/model/model.py
index 7cb01ba7b78dd198270477dbcccc37a8cc45e8de..66649015cc73cb80bd8ac7b98081333179ea27f9 100644
--- a/swh/model/model.py
+++ b/swh/model/model.py
@@ -25,6 +25,7 @@ from .identifiers import (
     release_identifier,
     snapshot_identifier,
     SWHID,
+    parse_swhid,
 )
 
 
@@ -58,6 +59,8 @@ def dictify(value):
     "Helper function used by BaseModel.to_dict()"
     if isinstance(value, BaseModel):
         return value.to_dict()
+    elif isinstance(value, SWHID):
+        return str(value)
     elif isinstance(value, Enum):
         return value.value
     elif isinstance(value, (dict, ImmutableDict)):
@@ -742,6 +745,17 @@ class MetadataAuthority(BaseModel):
         converter=freeze_optional_dict,
     )
 
+    def to_dict(self):
+        d = super().to_dict()
+        if d["metadata"] is None:
+            del d["metadata"]
+        return d
+
+    @classmethod
+    def from_dict(cls, d):
+        d["type"] = MetadataAuthorityType(d["type"])
+        return super().from_dict(d)
+
 
 @attr.s(frozen=True)
 class MetadataFetcher(BaseModel):
@@ -757,6 +771,12 @@ class MetadataFetcher(BaseModel):
         converter=freeze_optional_dict,
     )
 
+    def to_dict(self):
+        d = super().to_dict()
+        if d["metadata"] is None:
+            del d["metadata"]
+        return d
+
 
 class MetadataTargetType(Enum):
     """The type of object extrinsic metadata refer to."""
@@ -929,3 +949,38 @@ class RawExtrinsicMetadata(BaseModel):
 
         if pid.metadata:
             raise ValueError(f"Expected core SWHID, but got: {pid}")
+
+    def to_dict(self):
+        d = super().to_dict()
+        context_keys = (
+            "origin",
+            "visit",
+            "snapshot",
+            "release",
+            "revision",
+            "directory",
+            "path",
+        )
+        for context_key in context_keys:
+            if d[context_key] is None:
+                del d[context_key]
+        return d
+
+    @classmethod
+    def from_dict(cls, d):
+        d = {
+            **d,
+            "type": MetadataTargetType(d["type"]),
+            "authority": MetadataAuthority.from_dict(d["authority"]),
+            "fetcher": MetadataFetcher.from_dict(d["fetcher"]),
+        }
+
+        if d["type"] != MetadataTargetType.ORIGIN:
+            d["id"] = parse_swhid(d["id"])
+
+        swhid_keys = ("snapshot", "release", "revision", "directory")
+        for swhid_key in swhid_keys:
+            if d.get(swhid_key):
+                d[swhid_key] = parse_swhid(d[swhid_key])
+
+        return super().from_dict(d)
diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py
index 43c32a0c0eb09d8fffa0b5280cdea5f763fc24cc..b6aa82cb6d081221499ea9e3ad639f28b167c7b8 100644
--- a/swh/model/tests/test_model.py
+++ b/swh/model/tests/test_model.py
@@ -716,6 +716,38 @@ def test_metadata_valid():
     )
 
 
+def test_metadata_to_dict():
+    """Checks valid RawExtrinsicMetadata objects don't raise an error."""
+
+    common_fields = {
+        "authority": {"type": "forge", "url": "https://forge.softwareheritage.org",},
+        "fetcher": {"name": "test-fetcher", "version": "0.0.1",},
+        "discovery_date": _common_metadata_fields["discovery_date"],
+        "format": "json",
+        "metadata": b'{"foo": "bar"}',
+    }
+
+    m = RawExtrinsicMetadata(
+        type=MetadataTargetType.ORIGIN, id=_origin_url, **_common_metadata_fields
+    )
+    assert m.to_dict() == {
+        "type": "origin",
+        "id": _origin_url,
+        **common_fields,
+    }
+    assert RawExtrinsicMetadata.from_dict(m.to_dict()) == m
+
+    m = RawExtrinsicMetadata(
+        type=MetadataTargetType.CONTENT, id=_content_swhid, **_common_metadata_fields
+    )
+    assert m.to_dict() == {
+        "type": "content",
+        "id": "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2",
+        **common_fields,
+    }
+    assert RawExtrinsicMetadata.from_dict(m.to_dict()) == m
+
+
 def test_metadata_invalid_id():
     """Checks various invalid values for the 'id' field."""