cattrs
cattrs copied to clipboard
How to serialize (JSON) a type reference?
(I know it's not a cattrs issue.) I'm looking for a way to JSON-serialize a type-ref inside a attrs-class. But type-refs aren't supported by json-lib. See a litte example:
import attrs, cattrs, json
@attrs.mutable
class A:
my_type: type
@attrs.mutable
class B:
foo: int
a1=A(my_type=B)
a1u=cattrs.unstructure(a1)
a1uj=json.dumps(a1u)
Traceback (most recent call last):
File "C:\Python310\lib\code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
File "C:\Python310\lib\json\__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "C:\Python310\lib\json\encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "C:\Python310\lib\json\encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "C:\Python310\lib\json\encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type type is not JSON serializable
Are there any ideas on how to achieve my goal?
What json output are you expecting?
I want to make the de-serialization as generic as possible for various attrs classes (their instances are sent as JSON messages via MQTT). For this purpose, the respective type information should be contained in the message (in a container). Since this information is needed by cattrs.structure. My current work-around is to store the type information as str-value.
Do you only want the class name in the JSON payload, or more information?
To rebuild a type object one needs the class name (my_type.__name__) and the module name (my_type.__module__):
my_type: type = getattr(importlib.import_module(<module-name>), <class-name>)
At the moment I store these two values. I'm sure this could be done via hooks, which I haven't looked into yet.
But maybe a general json-lib support for type-object would be the better.
Interesting, ok. We're working on what we're calling tagged union support, this sounds like it. It's un/structuring a union with some metadata attached so it can be recreated on the other end.
Looks like you want the metadata to be a fully-qualified name for a class, and the structuring hook to import it. I'll keep this use case in mind.
Looks like you want the metadata to be a fully-qualified name for a class, and the structuring hook to import it.
Yes, this is what I want.