[O] json support more types

This commit is contained in:
Hykilpikonna
2022-12-19 01:10:31 -05:00
parent 1325224fd8
commit cb6aff290d
+45 -29
View File
@@ -4,9 +4,11 @@ import base64
import dataclasses import dataclasses
import datetime import datetime
import hashlib import hashlib
import inspect
import io import io
import json import json
import pickle import pickle
from enum import EnumType, Enum
from pathlib import Path from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
from typing import Any from typing import Any
@@ -37,36 +39,47 @@ def pickle_decode(by: bytes) -> Any:
return pickle.load(bio) return pickle.load(bio)
def infer(o: object) -> object | None:
# Support encoding dataclasses
# https://stackoverflow.com/a/51286749/7346633
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
# Simple namespace
if isinstance(o, SimpleNamespace):
return o.__dict__
# Support encoding datetime
if isinstance(o, (datetime.datetime, datetime.date)):
return o.isoformat()
# Support for sets
# https://stackoverflow.com/a/8230505/7346633
if isinstance(o, set):
return list(o)
# Support for Path
if isinstance(o, Path):
return str(o)
# Support for byte arrays (encode as base64 string)
if isinstance(o, bytes):
return base64.b64encode(o).decode()
# Enums
if isinstance(o, Enum):
return o.name
return None
class EnhancedJSONEncoder(json.JSONEncoder): class EnhancedJSONEncoder(json.JSONEncoder):
""" """
An improvement to the json.JSONEncoder class, which supports: An improvement to the json.JSONEncoder class, which supports:
encoding for dataclasses, encoding for datetime, and sets encoding for dataclasses, encoding for datetime, and sets
""" """
def default(self, o: object) -> object: def default(self, o: object) -> object:
return infer(o) or super().default(o)
# Support encoding dataclasses
# https://stackoverflow.com/a/51286749/7346633
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
# Simple namespace
if isinstance(o, SimpleNamespace):
return o.__dict__
# Support encoding datetime
if isinstance(o, (datetime.datetime, datetime.date)):
return o.isoformat()
# Support for sets
# https://stackoverflow.com/a/8230505/7346633
if isinstance(o, set):
return list(o)
# Support for Path
if isinstance(o, Path):
return str(o)
return super().default(o)
class ForceJSONEcoder(EnhancedJSONEncoder): class ForceJSONEcoder(EnhancedJSONEncoder):
@@ -74,14 +87,17 @@ class ForceJSONEcoder(EnhancedJSONEncoder):
A json encoder that can serialize almost everything (including custom classes, byte arrays) A json encoder that can serialize almost everything (including custom classes, byte arrays)
""" """
def default(self, o: object) -> object: def default(self, o: object) -> object:
infer_result = infer(o)
if infer_result:
return infer_result
# Support for byte arrays (encode as base64 string) # Support EnumType
if isinstance(o, bytes): if isinstance(o, EnumType):
return base64.b64encode(o).decode() return {i.name: i.value for i in o}
# Support for custom classes (get dict values) # Support for custom classes (get dict values)
if hasattr(o, '__dict__'): if hasattr(o, '__dict__') and not inspect.isclass(o):
return vars(o) return dict(vars(o))
return super().default(o) return super().default(o)