test_non_str_keys.py
Overview
`test_non_str_keys.py` is a comprehensive test suite designed to verify the behavior of the `orjson` JSON serialization library when serializing dictionary keys that are **not strings**. The file specifically tests the `OPT_NON_STR_KEYS` option, which enables serialization of non-string dictionary keys by converting them into string representations or handling them according to defined rules.
The tests cover a wide range of key types including integers, floats, booleans, datetime objects, UUIDs, custom subclasses of `str`, and invalid or unsupported types. The suite also verifies the interaction of `OPT_NON_STR_KEYS` with other `orjson` serialization options and error conditions.
The goal is to ensure consistent, predictable, and correct serialization behavior when dictionaries with non-string keys are serialized using `orjson`.
Classes and Functions
Class: SubStr(str)
Description: A simple subclass of Python’s built-in
strclass.Purpose: Used in tests to verify behavior with string subclasses and how
orjsonhandles them when serializing dictionary keys.Properties/Methods: Inherits all from
strwithout modification.
Class: TestNonStrKeyTests
This class contains multiple test methods, each verifying a particular aspect of `orjson`’s handling of non-string dictionary keys with the `OPT_NON_STR_KEYS` option.
All tests use `pytest` framework conventions.
Test Methods
Each method tests serialization behavior or error handling for specific key types or option combinations.
test_dict_keys_duplicate(self)
Purpose: Tests serialization of dictionaries with duplicate keys when using
OPT_NON_STR_KEYS.Behavior: Both
"1"(string) and1(integer) keys serialize to the same string"1", so output contains duplicate keys.Expected Output:
b'{"1":true,"1":false}'
test_dict_keys_int(self)
Purpose: Tests integer keys serialization.
Parameters: None.
Expected Output: Integers as keys serialize to their string equivalents, e.g.,
b'{"1":true,"2":false}'.
test_dict_keys_substr(self)
Purpose: Tests keys that are instances of the
SubStrsubclass ofstr.Expected Output: Key serializes as the string value, e.g.,
b'{"aaa":true}'.
test_dict_keys_substr_passthrough(self)
Purpose: Verifies that OPT_PASSTHROUGH_SUBCLASS option does not affect
OPT_NON_STR_KEYS.Expected Output: Same as
test_dict_keys_substr.
test_dict_keys_substr_invalid(self)
Purpose: Checks behavior with invalid surrogate Unicode characters in string keys.
Expected Behavior: Raises orjson.JSONEncodeError.
test_dict_keys_strict(self)
Purpose: Tests that
OPT_NON_STR_KEYSignores OPT_STRICT_INTEGER restrictions.Expected Output: Large integers serialize as strings without error.
test_dict_keys_int_range_valid_i64(self)
Purpose: Tests serialization of integers within signed 64-bit integer range.
Expected Output: Valid large positive and negative integers serialize correctly.
test_dict_keys_int_range_valid_u64(self)
Purpose: Tests serialization of integers in unsigned 64-bit integer range.
Expected Output: Zero and max unsigned 64-bit integer serialize correctly.
test_dict_keys_int_range_invalid(self)
Purpose: Tests integers outside valid range (less than i64 min or greater than u64 max).
Expected Behavior: Raises orjson.JSONEncodeError.
test_dict_keys_float(self)
Purpose: Tests serialization when keys are floats.
Expected Output: Floats convert to their string representations.
test_dict_keys_inf(self)
Purpose: Tests serialization of infinite float keys.
Expected Output: Serialized as
"null".
test_dict_keys_nan(self)
Purpose: Tests serialization of NaN float keys.
Expected Output: Serialized as
"null".
test_dict_keys_bool(self)
Purpose: Tests boolean keys serialization.
Expected Output: Booleans serialize as
"true"and"false"strings.
test_dict_keys_datetime(self)
Purpose: Tests serialization of
datetime.datetimeobjects as keys.Expected Output: ISO 8601 formatted string including microseconds.
test_dict_keys_datetime_opt(self)
Purpose: Tests serialization of datetime keys with additional options:
OPT_OMIT_MICROSECONDS: omit microseconds.OPT_NAIVE_UTC: treat naive times as UTC.OPT_UTC_Z: use 'Z' suffix for UTC.
Expected Output: ISO 8601 string without microseconds and with 'Z' suffix.
test_dict_keys_datetime_passthrough(self)
Purpose: Verifies that OPT_PASSTHROUGH_DATETIME does not impact
OPT_NON_STR_KEYSbehavior.Expected Output: Same as default datetime serialization with microseconds.
test_dict_keys_uuid(self)
Purpose: Tests serialization of UUID keys.
Expected Output: UUID keys serialize as their canonical string format.
test_dict_keys_date(self)
Purpose: Tests serialization of
datetime.datekeys.Expected Output: ISO 8601 date string.
test_dict_keys_time(self)
Purpose: Tests serialization of datetime.time keys.
Expected Output: Time string including microseconds.
test_dict_non_str_and_sort_keys(self)
Purpose: Tests serialization with both
OPT_NON_STR_KEYSand OPT_SORT_KEYS enabled.Expected Output: Keys are serialized as strings and sorted lexicographically.
test_dict_keys_time_err(self)
Purpose: Tests that time objects with timezone info from
pytzraise errors.Condition: Skipped if
pytzis not installed.Expected Behavior: Raises orjson.JSONEncodeError.
test_dict_keys_str(self)
Purpose: Tests serialization of string keys with
OPT_NON_STR_KEYS(should behave like normal strings).Expected Output: Keys serialize as usual.
test_dict_keys_type(self)
Purpose: Tests that arbitrary objects as keys cause serialization failure.
Expected Behavior: Raises orjson.JSONEncodeError.
test_dict_keys_array(self)
Purpose: Tests that numpy arrays cannot be used as dictionary keys.
Condition: Skipped if
numpyis not installed.Expected Behavior: Raises TypeError on dictionary creation (before serialization).
test_dict_keys_dataclass(self)
Purpose: Tests that dataclass instances are invalid dictionary keys.
Expected Behavior: Raises TypeError on dictionary creation.
test_dict_keys_dataclass_hash(self)
Purpose: Tests dataclass with a custom
__hash__method as dictionary key.Expected Behavior: Serialization raises orjson.JSONEncodeError.
test_dict_keys_list(self)
Purpose: Tests that lists as dictionary keys raise errors.
Expected Behavior: Raises TypeError on dictionary creation.
test_dict_keys_dict(self)
Purpose: Tests that dictionaries as keys raise errors.
Expected Behavior: Raises TypeError on dictionary creation.
test_dict_keys_tuple(self)
Purpose: Tests tuples as dictionary keys (empty tuple).
Expected Behavior: Serialization raises orjson.JSONEncodeError.
test_dict_keys_unknown(self)
Purpose: Tests unknown or unsupported types (e.g.,
frozenset) as dictionary keys.Expected Behavior: Serialization raises orjson.JSONEncodeError.
test_dict_keys_no_str_call(self)
Purpose: Tests that objects with
__str__method are not serialized as keys unless explicitly supported.Expected Behavior: Serialization raises orjson.JSONEncodeError.
Important Implementation Details
The test suite uses the orjson.dumps() function with the
optionparameter set to various combinations of serialization flags provided byorjson, focusing primarily onOPT_NON_STR_KEYS.The
OPT_NON_STR_KEYSoption enables serialization of dictionary keys that are not strings by converting them to strings where possible.The tests confirm that only certain types are supported as dictionary keys under this option (e.g., int, float, bool, datetime, UUID), and that unsupported types or invalid values raise serialization errors.
The suite also verifies that certain options (like OPT_PASSTHROUGH_SUBCLASS or OPT_PASSTHROUGH_DATETIME) do not interfere with the behavior of
OPT_NON_STR_KEYS.Error handling is rigorously tested, ensuring that the library raises orjson.JSONEncodeError or Python TypeError as appropriate when unsupported keys or invalid values are encountered.
The file also includes conditional tests that depend on the availability of optional dependencies (
pytzandnumpy).
Interaction with Other Parts of the System
This file interacts primarily with the
orjsonlibrary, testing its serialization behavior.It imports a
numpyutility from a relative .util module, used to conditionally test behavior related to numpy arrays.The tests rely on
pytestfor test execution and assertions.The presence of
pytz(optional timezone library) affects certain timezone-related tests.This test file is part of a larger test suite for
orjsonand ensures the robustness of its JSON serialization features related to dictionary key handling.No other system components or application layers are directly involved.
Usage Examples
Below are representative examples derived from tests showing how `orjson` serializes dictionaries with non-string keys when using `OPT_NON_STR_KEYS`:
import orjson
import datetime
import uuid
# Integer keys serialize as strings
print(orjson.dumps({1: True, 2: False}, option=orjson.OPT_NON_STR_KEYS))
# Output: b'{"1":true,"2":false}'
# Datetime keys serialize as ISO 8601 strings
dt = datetime.datetime(2023, 6, 15, 12, 30, 0)
print(orjson.dumps({dt: "value"}, option=orjson.OPT_NON_STR_KEYS))
# Output: b'{"2023-06-15T12:30:00": "value"}'
# UUID keys serialize as their canonical string
uid = uuid.UUID("7202d115-7ff3-4c81-a7c1-2a1f067b1ece")
print(orjson.dumps({uid: True}, option=orjson.OPT_NON_STR_KEYS))
# Output: b'{"7202d115-7ff3-4c81-a7c1-2a1f067b1ece":true}'
# Boolean keys serialize as "true" and "false" strings
print(orjson.dumps({True: 1, False: 0}, option=orjson.OPT_NON_STR_KEYS))
# Output: b'{"true":1,"false":0}'
Mermaid Diagram: Test Class Structure
classDiagram
class SubStr {
<<str subclass>>
}
class TestNonStrKeyTests {
+test_dict_keys_duplicate()
+test_dict_keys_int()
+test_dict_keys_substr()
+test_dict_keys_substr_passthrough()
+test_dict_keys_substr_invalid()
+test_dict_keys_strict()
+test_dict_keys_int_range_valid_i64()
+test_dict_keys_int_range_valid_u64()
+test_dict_keys_int_range_invalid()
+test_dict_keys_float()
+test_dict_keys_inf()
+test_dict_keys_nan()
+test_dict_keys_bool()
+test_dict_keys_datetime()
+test_dict_keys_datetime_opt()
+test_dict_keys_datetime_passthrough()
+test_dict_keys_uuid()
+test_dict_keys_date()
+test_dict_keys_time()
+test_dict_non_str_and_sort_keys()
+test_dict_keys_time_err()
+test_dict_keys_str()
+test_dict_keys_type()
+test_dict_keys_array()
+test_dict_keys_dataclass()
+test_dict_keys_dataclass_hash()
+test_dict_keys_list()
+test_dict_keys_dict()
+test_dict_keys_tuple()
+test_dict_keys_unknown()
+test_dict_keys_no_str_call()
}
TestNonStrKeyTests ..> orjson : uses
TestNonStrKeyTests ..> pytest : uses
TestNonStrKeyTests ..> numpy : conditional
TestNonStrKeyTests ..> pytz : conditional
Summary
`test_non_str_keys.py` is a focused test suite that rigorously ensures the `orjson` library correctly handles dictionary keys that are not strings, under the `OPT_NON_STR_KEYS` serialization option. It covers valid and invalid key types, interactions with other serialization options, and error handling scenarios. This file is critical for maintaining the correctness and robustness of `orjson`’s flexible key serialization capabilities.