from __future__ import annotations import json from typing import Any from aiohttp import web class EnhancedJSONEncoder(json.JSONEncoder): """ Encodes bytes as hex strings with 0x, and converts all dataclasses to json. """ def default(self, o: Any) -> Any: if hasattr(type(o), "to_json_dict"): return o.to_json_dict() elif hasattr(type(o), "__bytes__"): return f"0x{bytes(o).hex()}" elif isinstance(o, bytes): return f"0x{o.hex()}" return super().default(o) def dict_to_json_str(o: Any) -> str: """ Converts a python object into json. """ json_str = json.dumps(o, cls=EnhancedJSONEncoder, sort_keys=True) return json_str def obj_to_response(o: Any) -> web.Response: """ Converts a python object into json. Used for RPC server which returns JSON. """ json_str = dict_to_json_str(o) return web.Response(body=json_str, content_type="application/json")