diff --git a/optuna_dashboard/serializer.py b/optuna_dashboard/serializer.py index e164ff78..7b05bf22 100644 --- a/optuna_dashboard/serializer.py +++ b/optuna_dashboard/serializer.py @@ -1,4 +1,3 @@ -import json from typing import Any, Dict, List, Tuple from optuna.distributions import BaseDistribution @@ -11,6 +10,7 @@ except ImportError: from typing_extensions import TypedDict +MAX_ATTR_LENGTH = 128 Attribute = TypedDict( "Attribute", { @@ -35,7 +35,21 @@ TrialParam = TypedDict( def serialize_attrs(attrs: Dict[str, Any]) -> List[Attribute]: - return [{"key": k, "value": json.dumps(v)} for k, v in attrs.items()] + serialized: List[Attribute] = [] + for k, v in attrs.items(): + value: str + if isinstance(v, str): + value = v[:MAX_ATTR_LENGTH] if len(v) > MAX_ATTR_LENGTH else v + elif isinstance(v, (bool, float, int)): + value = str(v) + elif isinstance(v, bytes): + value = "" + elif v is None: + value = "None" + else: # unsupported type + continue + serialized.append({"key": k, "value": value}) + return serialized def serialize_intermediate_values(values: Dict[int, float]) -> List[IntermediateValue]: diff --git a/tests/test_serializers.py b/tests/test_serializers.py new file mode 100644 index 00000000..d95f6f9a --- /dev/null +++ b/tests/test_serializers.py @@ -0,0 +1,19 @@ +from unittest import TestCase +from optuna_dashboard.serializer import serialize_attrs + + +class SerializeAttrsTestCase(TestCase): + def test_serialize_bytes(self) -> None: + serialized = serialize_attrs({"bytes": b"This is a bytes object."}) + self.assertEqual(serialized[0]["value"], "") + + def test_serialize_string(self) -> None: + for length in [100, 128, 150]: + with self.subTest(f"length: {length}"): + value = "a" * length + serialized = serialize_attrs( + { + "key": value, + } + ) + self.assertLessEqual(len(serialized[0]["value"]), 128)