Skip to content

fix: JsonableData strips @module and @class before passing dict to from_dict(), breaking MSONable round-trips #7596

Description

@rautaditya2606

Describe the bug

JsonableData._get_object() calls .pop('@class') and .pop('@module') on the attributes dictionary before passing it to cls.from_dict(). This mutates the dict and strips both keys before deserialization. MSONable's contract (used by pymatgen and other materials science libraries) requires @module and @class to be present in the dict passed to from_dict() — the same dict that as_dict() produced. Stripping them silently breaks round-trip deserialization.

Steps to reproduce

from aiida.orm import JsonableData, load_node

class MyMSONable:
    def __init__(self, value):
        self.value = value

    def as_dict(self):
        return {
            '@module': self.__class__.__module__,
            '@class': self.__class__.__name__,
            'value': self.value,
        }

    @classmethod
    def from_dict(cls, d):
        # MSONable contract: @module and @class must be present
        if '@module' not in d or '@class' not in d:
            raise KeyError('`@module` and `@class` must be present')
        return cls(d['value'])

obj = MyMSONable(42)
node = JsonableData(obj)
node.store()

loaded = load_node(node.pk)
print(loaded.obj.value)  # Raises KeyError: @module and @class stripped

Expected behavior

loaded.obj.value should return 42. @module and @class should be preserved in the dict passed to cls.from_dict().

Your environment

  • Operating system: Linux
  • Python version: 3.11
  • aiida-core version: 2.8.0 (main branch)

Additional context

File: src/aiida/orm/nodes/data/jsonable.py

The fix is to use non-destructive key access (attributes['@class']) instead of .pop(), so the full dict including @module and @class reaches from_dict(). A PR with the fix and a regression test is ready.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    Priority

    Low

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions