Skip to content

Instantly share code, notes, and snippets.

@jiwnchoi
Created March 14, 2024 06:26
Show Gist options
  • Save jiwnchoi/60eb1a7aca8aaf91d3f67a815fde8036 to your computer and use it in GitHub Desktop.
Save jiwnchoi/60eb1a7aca8aaf91d3f67a815fde8036 to your computer and use it in GitHub Desktop.
dataclass json encoder / decoder
from __future__ import annotations
from dataclasses import asdict, is_dataclass
from json import JSONDecoder, JSONEncoder
from typing import Type, TypeVar
T = TypeVar("T")
class VJSONEncoder(JSONEncoder):
def default(self, o):
if is_dataclass(o):
return asdict(o)
return super().default(o)
class VJSONDecoder(JSONDecoder):
def __init__(self, schemas: list[Type[T]], *args, **kwargs):
super().__init__(object_hook=self.object_hook, *args, **kwargs)
for schema in schemas:
if not is_dataclass(schema):
raise TypeError(f"{schema} is not a dataclass")
self.schemas = schemas
def object_hook(self, o):
# check if the object's is dictionary form one of the schemas
for schema in self.schemas:
if all(annotation in o for annotation in schema.__annotations__) and all(
key in schema.__annotations__ for key in o
):
return schema(**o)
return o
def dumps(obj, *args, **kwargs):
return VJSONEncoder(*args, **kwargs).encode(obj)
def loads(s, *args, **kwargs):
return VJSONDecoder(*args, **kwargs).decode(s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment