Skip to content

Commit

Permalink
move all type conversions in json handler
Browse files Browse the repository at this point in the history
removes duplicate code
  • Loading branch information
marcelveldt committed Jun 22, 2023
1 parent 0e61262 commit 0a658f2
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 40 deletions.
8 changes: 7 additions & 1 deletion matter_server/common/helpers/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from dataclasses import is_dataclass
from typing import Any

from chip.clusters.Attribute import ValueDecodeFailure
from chip.clusters.Types import Nullable
from chip.tlv import float32, uint
import orjson

from .util import dataclass_to_dict
Expand All @@ -20,10 +22,14 @@ def json_encoder_default(obj: Any) -> Any:
"""
if getattr(obj, "do_not_serialize", None):
return None
if isinstance(obj, ValueDecodeFailure):
return None
if isinstance(obj, (set, tuple)):
return list(obj)
if isinstance(obj, float):
if isinstance(obj, float32):
return float(obj)
if isinstance(obj, uint):
return int(obj)
if hasattr(obj, "as_dict"):
return obj.as_dict()
if is_dataclass(obj):
Expand Down
51 changes: 12 additions & 39 deletions matter_server/common/helpers/util.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Utils for Matter server (and client)."""
from __future__ import annotations

from base64 import b64decode, b64encode
from base64 import b64decode
import binascii
from dataclasses import MISSING, asdict, fields, is_dataclass
from datetime import datetime
Expand All @@ -22,7 +22,7 @@
)

from chip.clusters.ClusterObjects import ClusterAttributeDescriptor
from chip.clusters.Types import Nullable, NullValue
from chip.clusters.Types import Nullable
from chip.tlv import float32, uint

if TYPE_CHECKING:
Expand Down Expand Up @@ -59,44 +59,17 @@ def parse_attribute_path(attribute_path: str) -> tuple[int, int, int]:
return (int(endpoint_id_str), int(cluster_id_str), int(attribute_id_str))


def dataclass_to_dict(obj_in: DataclassInstance, skip_none: bool = False) -> dict:
"""Convert dataclass instance to dict, optionally skip None values."""
if skip_none:
dict_obj = asdict(
obj_in, dict_factory=lambda x: {k: v for (k, v) in x if v is not None}
)
else:
dict_obj = asdict(obj_in)

def _convert_value(value: Any) -> Any:
"""Do some common conversions."""
if isinstance(value, list):
return [_convert_value(x) for x in value]
if isinstance(value, Nullable) or value == NullValue:
return None
if isinstance(value, dict):
return _clean_dict(value)
if isinstance(value, Enum):
return value.value
if isinstance(value, bytes):
return b64encode(value).decode("utf-8")
if isinstance(value, float32):
return float(value)
if type(value) == type:
return f"{value.__module__}.{value.__qualname__}"
if isinstance(value, Exception):
return None
return value
def dataclass_to_dict(obj_in: DataclassInstance) -> dict:
"""Convert dataclass instance to dict."""

def _clean_dict(_dict_obj: dict) -> dict:
_final = {}
for key, value in _dict_obj.items():
if isinstance(key, int):
key = str(key)
_final[key] = _convert_value(value)
return _final

return _clean_dict(dict_obj)
return asdict(
obj_in,
dict_factory=lambda x: {
# ensure the dict key is a string
str(k): v
for (k, v) in x
},
)


def parse_utc_timestamp(datetime_string: str) -> datetime:
Expand Down

0 comments on commit 0a658f2

Please sign in to comment.