diff --git a/okonomiyaki/file_formats/_egg_info.py b/okonomiyaki/file_formats/_egg_info.py
index ddc2e2f..afc373c 100644
--- a/okonomiyaki/file_formats/_egg_info.py
+++ b/okonomiyaki/file_formats/_egg_info.py
@@ -663,6 +663,18 @@ def _normalized_info_from_string(spec_depend_string, epd_platform=None,
     return data, epd_platform
 
 
+_JSON_METADATA_VERSION = "metadata_version"
+_JSON__RAW_NAME = "_raw_name"
+_JSON_VERSION = "version"
+_JSON_EPD_PLATFORM = "epd_platform"
+_JSON_PYTHON_TAG = "python_tag"
+_JSON_ABI_TAG = "abi_tag"
+_JSON_PLATFORM_TAG = "platform_tag"
+_JSON_PLATFORM_ABI_TAG = "platform_abi_tag"
+_JSON_RUNTIME_DEPENDENCIES = "runtime_dependencies"
+_JSON_SUMMARY = "summary"
+
+
 class EggMetadata(object):
     """ Enthought egg metadata for format 1.x.
     """
@@ -707,6 +719,32 @@ class EggMetadata(object):
                 sha256 = compute_sha256(path_or_file.fp)
         return cls._from_egg(path_or_file, sha256, strict)
 
+    @classmethod
+    def from_json_dict(cls, json_dict, pkg_info):
+        version = EnpkgVersion.from_string(json_dict[_JSON_VERSION])
+
+        if json_dict[_JSON_PYTHON_TAG] is not None:
+            python = PythonImplementation.from_string(json_dict[_JSON_PYTHON_TAG])
+        else:
+            python = None
+
+        if json_dict[_JSON_EPD_PLATFORM] is None:
+            epd_platform = None
+        else:
+            epd_platform = EPDPlatform.from_epd_string(json_dict[_JSON_EPD_PLATFORM])
+
+        dependencies = Dependencies(tuple(json_dict[_JSON_RUNTIME_DEPENDENCIES]))
+        metadata_version = MetadataVersion.from_string(
+            json_dict[_JSON_METADATA_VERSION]
+        )
+
+        return cls(
+            json_dict[_JSON__RAW_NAME], version, epd_platform, python,
+            json_dict[_JSON_ABI_TAG], json_dict[_JSON_PLATFORM_ABI_TAG],
+            dependencies, pkg_info, json_dict[_JSON_SUMMARY],
+            metadata_version=metadata_version
+        )
+
     @classmethod
     def _from_egg(cls, path_or_file, sha256, strict=True):
         def _read_summary(fp):
@@ -1015,6 +1053,27 @@ class EggMetadata(object):
             if self.pkg_info:
                 self.pkg_info._dump_as_zip(zp)
 
+    def to_json_dict(self):
+        if self.platform is None:
+            epd_platform = None
+        else:
+            epd_platform = six.text_type(self.platform)
+
+        return {
+            _JSON_METADATA_VERSION: six.text_type(self.metadata_version),
+            _JSON__RAW_NAME: self._raw_name,
+            _JSON_VERSION: six.text_type(self.version),
+            _JSON_EPD_PLATFORM: epd_platform,
+            _JSON_PYTHON_TAG: self.python_tag,
+            _JSON_ABI_TAG: self.abi_tag,
+            _JSON_PLATFORM_TAG: self.platform_tag,
+            _JSON_PLATFORM_ABI_TAG: self.platform_abi_tag,
+            _JSON_RUNTIME_DEPENDENCIES: [
+                six.text_type(p) for p in self.runtime_dependencies
+            ],
+            _JSON_SUMMARY: self.summary,
+        }
+
     # Protocol implementations
     def __eq__(self, other):
         if isinstance(other, self.__class__):

Move EggMetadata json serialization from edm 
See enthought/edm#719
diff --git a/okonomiyaki/file_formats/tests/test__egg_info.py b/okonomiyaki/file_formats/tests/test__egg_info.py
index 80dd58b..b658c36 100644
--- a/okonomiyaki/file_formats/tests/test__egg_info.py
+++ b/okonomiyaki/file_formats/tests/test__egg_info.py
@@ -17,7 +17,9 @@ from ...errors import (
     InvalidEggName, InvalidMetadata, InvalidMetadataField, MissingMetadata,
     UnsupportedMetadata)
 from ...utils import tempdir
-from ...utils.test_data import NOSE_1_3_4_OSX_X86_64
+from ...utils.test_data import (
+    MKL_10_3_RH5_X86_64, NOSE_1_3_4_OSX_X86_64, NOSE_1_3_4_RH5_X86_64
+)
 from ...platforms import EPDPlatform, PlatformABI, PythonImplementation
 from ...platforms.legacy import LegacyEPDPlatform
 from ...versions import EnpkgVersion, MetadataVersion, RuntimeVersion
@@ -1552,3 +1554,68 @@ class TestEggMetadata(unittest.TestCase):
         # Then
         metadata = EggMetadata.from_egg(path)
         self.assertEqual(metadata.platform_tag, "win32")
+
+    def test_to_json_dict(self):
+        # Given
+        egg = NOSE_1_3_4_RH5_X86_64
+        metadata = EggMetadata.from_egg(egg)
+
+        r_json_dict = {
+            "metadata_version": u"1.3",
+            "_raw_name": u"nose",
+            "version": u"1.3.4-1",
+            "epd_platform": u"rh5_x86_64",
+            "python_tag": u"cp27",
+            "abi_tag": u"cp27m",
+            "platform_tag": u"linux_x86_64",
+            "platform_abi_tag": u"gnu",
+            "runtime_dependencies": [],
+            "summary": (
+                u"Extends the Python Unittest module with additional "
+                "disocvery and running\noptions\n"
+            )
+        }
+
+        # When
+        json_dict = metadata.to_json_dict()
+
+        # Then
+        self.assertEqual(json_dict, r_json_dict)
+
+    def test_from_json_dict(self):
+        # Given
+        egg = NOSE_1_3_4_RH5_X86_64
+        r_metadata = EggMetadata.from_egg(egg)
+
+        json_dict = {
+            "metadata_version": u"1.3",
+            "_raw_name": u"nose",
+            "version": u"1.3.4-1",
+            "epd_platform": u"rh5_x86_64",
+            "python_tag": u"cp27",
+            "abi_tag": u"cp27m",
+            "platform_tag": u"linux_x86_64",
+            "platform_abi_tag": u"gnu",
+            "runtime_dependencies": [],
+            "summary": (
+                u"Extends the Python Unittest module with additional "
+                "disocvery and running\noptions\n"
+            )
+        }
+
+        # When
+        metadata = EggMetadata.from_json_dict(json_dict, r_metadata.pkg_info)
+
+        # Then
+        self.assertEqual(metadata, r_metadata)
+
+    def _test_roundtrip(self, egg):
+        r_metadata = EggMetadata.from_egg(egg)
+        metadata = EggMetadata.from_json_dict(
+            r_metadata.to_json_dict(), r_metadata.pkg_info
+        )
+
+        self.assertEqual(metadata, r_metadata)
+
+    def test_mkl_roundtrip(self):
+        self._test_roundtrip(MKL_10_3_RH5_X86_64)

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.9
dev_requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==25.3.0
coverage==7.8.0
docutils==0.21.2
enum34==1.1.10
exceptiongroup==1.2.2
flake8==7.2.0
haas==0.9.0
iniconfig==2.1.0
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
mccabe==0.7.0
mock==1.0.1
-e git+https://github.com/enthought/okonomiyaki.git@a23c1b4909741d649ebd22f30dc1268712e63c0f#egg=okonomiyaki
packaging==24.2
pbr==6.1.1
pluggy==1.5.0
pycodestyle==2.13.0
pyflakes==3.3.2
pytest==8.3.5
referencing==0.36.2
rpds-py==0.24.0
six==1.17.0
statistics==1.0.3.5
stevedore==4.1.1
testfixtures==8.3.0
tomli==2.2.1
typing_extensions==4.13.0
zipfile2==0.0.12

name: okonomiyaki
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==25.3.0
      - coverage==7.8.0
      - docutils==0.21.2
      - enum34==1.1.10
      - exceptiongroup==1.2.2
      - flake8==7.2.0
      - haas==0.9.0
      - iniconfig==2.1.0
      - jsonschema==4.23.0
      - jsonschema-specifications==2024.10.1
      - mccabe==0.7.0
      - mock==1.0.1
      - packaging==24.2
      - pbr==6.1.1
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.2
      - pytest==8.3.5
      - referencing==0.36.2
      - rpds-py==0.24.0
      - six==1.17.0
      - statistics==1.0.3.5
      - stevedore==4.1.1
      - testfixtures==8.3.0
      - tomli==2.2.1
      - typing-extensions==4.13.0
      - zipfile2==0.0.12
prefix: /opt/conda/envs/okonomiyaki

okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_from_json_dict okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_mkl_roundtrip okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_to_json_dict
okonomiyaki/file_formats/tests/test__egg_info.py::TestRequirement::test_from_spec_string okonomiyaki/file_formats/tests/test__egg_info.py::TestRequirement::test_from_string okonomiyaki/file_formats/tests/test__egg_info.py::TestRequirement::test_str okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_blacklisted_platform okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_create_from_egg1 okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_create_from_egg2 okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_error_python_to_python_tag okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_format_1_3 okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_format_1_4 okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_from_string okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_missing_spec_depend okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_to_string okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_unsupported_metadata_version okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDepend::test_windows_platform okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependAbi::test_default_extension_python_egg okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependAbi::test_default_no_python_egg okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependAbi::test_default_pure_python_egg okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependAbi::test_default_pure_python_egg_pypi okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependAbi::test_to_string okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependPlatform::test_default_all_none okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependPlatform::test_default_rh5_32 okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependPlatform::test_default_rh5_64 okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependPlatform::test_default_win_32 okonomiyaki/file_formats/tests/test__egg_info.py::TestLegacySpecDependPlatform::test_default_win_64 okonomiyaki/file_formats/tests/test__egg_info.py::TestGuessPlatformAbi::test_no_platform okonomiyaki/file_formats/tests/test__egg_info.py::TestGuessPlatformAbi::test_no_python_implementation okonomiyaki/file_formats/tests/test__egg_info.py::TestGuessPlatformAbi::test_python_27 okonomiyaki/file_formats/tests/test__egg_info.py::TestGuessPlatformAbi::test_python_34 okonomiyaki/file_formats/tests/test__egg_info.py::TestGuessPlatformAbi::test_python_35 okonomiyaki/file_formats/tests/test__egg_info.py::TestEggName::test_split_egg_name okonomiyaki/file_formats/tests/test__egg_info.py::TestEggName::test_split_egg_name_invalid okonomiyaki/file_formats/tests/test__egg_info.py::TestParseRawspec::test_invalid_spec_strings okonomiyaki/file_formats/tests/test__egg_info.py::TestParseRawspec::test_simple_1_1 okonomiyaki/file_formats/tests/test__egg_info.py::TestParseRawspec::test_simple_1_2 okonomiyaki/file_formats/tests/test__egg_info.py::TestParseRawspec::test_simple_unsupported okonomiyaki/file_formats/tests/test__egg_info.py::TestParseRawspec::test_with_dependencies okonomiyaki/file_formats/tests/test__egg_info.py::TestParseRawspec::test_with_none okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_blacklisted_pkg_info okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_blacklisted_platform okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_blacklisted_python_tag okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_dump_blacklisted okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_dump_blacklisted_platform okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_dump_simple okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_fixed_requirement okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_from_cross_platform_egg okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_from_platform_egg okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_no_pkg_info okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_platform_abi okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_platform_abi_no_python okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_simple okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_simple_non_python_egg okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_strictness okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_support_higher_compatible_version okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_support_lower_compatible_version okonomiyaki/file_formats/tests/test__egg_info.py::TestEggMetadata::test_to_spec_string
okonomiyaki/file_formats/_egg_info.py
okonomiyaki/file_formats/_egg_info.py