Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ui/sdk/src/hamilton_sdk/tracking/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ def make_json_safe(item: Union[dict, list, str, float, int, bool]) -> Any:
return make_json_safe(item.to_dict())
else:
try:
json.dumps(item) # Check if item is json serializable
json.dumps(item, allow_nan=False) # Check if item is json serializable
if isinstance(item, str):
# escape null byte -- postgres doesn't like null bytes at least.
# we might need to escape more things; TBD.
return item.replace("\x00", "\\x00")
return item
except TypeError:
except (TypeError, ValueError):
return str(item) # Convert item to string if not json serializable
25 changes: 25 additions & 0 deletions ui/sdk/tests/tracking/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,28 @@ def test_make_json_safe_str_with_null_byte():
assert isinstance(result, dict)
assert isinstance(result["key2"], str)
assert result["key2"] == "value\\x00"


def test_make_json_safe_with_nan():
"""Test that NaN and Infinity values are properly handled in make_json_safe"""
import math

# Test with a dictionary
input_dict = {"a": math.nan, "b": np.nan, "c": 1.0, "d": math.inf, "e": -math.inf}
result = utils.make_json_safe(input_dict)
assert isinstance(result, dict)
assert result["a"] == "nan" # NaN should be represented as "nan"
assert result["b"] == "nan" # …same for numpy.nan
assert result["c"] == 1.0 # Regular float should remain unchanged
assert result["d"] == "inf" # Infinity should be represented as "inf"
assert result["e"] == "-inf" # Negative infinity should be represented as "-inf"

# Test with a list
input_list = [math.nan, np.nan, 1.0, math.inf, -math.inf]
result = utils.make_json_safe(input_list)
assert isinstance(result, list)
assert result[0] == "nan" # NaN should be represented as "nan"
assert result[1] == "nan" # …same for numpy.nan
assert result[2] == 1.0 # Regular float should remain unchanged
assert result[3] == "inf" # Infinity should be represented as "inf"
assert result[4] == "-inf" # Negative infinity should be represented as "-inf"