-
Notifications
You must be signed in to change notification settings - Fork 105
fix: JsonObject array/scalar variants now implement standard dict protocol #1506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,3 +96,90 @@ def test_w_JsonObject_of_list_of_simple_JsonData(self): | |
| expected = json.dumps(data, sort_keys=True, separators=(",", ":")) | ||
| data_jsonobject = JsonObject(JsonObject(data)) | ||
| self.assertEqual(data_jsonobject.serialize(), expected) | ||
|
|
||
|
|
||
| class Test_JsonObject_dict_protocol(unittest.TestCase): | ||
| """Verify that JsonObject behaves correctly with standard Python | ||
| operations (len, bool, iteration, indexing) for all JSON variants.""" | ||
|
|
||
| def test_array_len(self): | ||
| obj = JsonObject([{"id": 1}, {"id": 2}]) | ||
| self.assertEqual(len(obj), 2) | ||
|
|
||
| def test_array_bool_truthy(self): | ||
| obj = JsonObject([{"id": 1}]) | ||
| self.assertTrue(obj) | ||
|
|
||
| def test_array_bool_empty(self): | ||
| obj = JsonObject([]) | ||
| self.assertFalse(obj) | ||
|
|
||
| def test_array_iter(self): | ||
| data = [{"a": 1}, {"b": 2}] | ||
| obj = JsonObject(data) | ||
| self.assertEqual(list(obj), data) | ||
|
|
||
| def test_array_getitem(self): | ||
| data = [{"a": 1}, {"b": 2}] | ||
| obj = JsonObject(data) | ||
| self.assertEqual(obj[0], {"a": 1}) | ||
| self.assertEqual(obj[1], {"b": 2}) | ||
|
|
||
| def test_array_contains(self): | ||
| data = [1, 2, 3] | ||
| obj = JsonObject(data) | ||
| self.assertIn(2, obj) | ||
| self.assertNotIn(4, obj) | ||
|
|
||
| def test_array_eq(self): | ||
| data = [{"id": 1}] | ||
| obj = JsonObject(data) | ||
| self.assertEqual(obj, data) | ||
|
|
||
| def test_array_json_dumps(self): | ||
| data = [{"id": "m1", "content": "hello"}] | ||
| obj = JsonObject(data) | ||
| result = json.loads(json.dumps(list(obj))) | ||
| self.assertEqual(result, data) | ||
|
Comment on lines
+139
to
+143
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name of this test, In fact, The core functionality this test verifies—that Given the misleading name and redundancy, I recommend removing this test to avoid confusion. |
||
|
|
||
| def test_dict_len(self): | ||
| obj = JsonObject({"a": 1, "b": 2}) | ||
| self.assertEqual(len(obj), 2) | ||
|
|
||
| def test_dict_bool(self): | ||
| obj = JsonObject({"a": 1}) | ||
| self.assertTrue(obj) | ||
|
|
||
| def test_dict_iter(self): | ||
| obj = JsonObject({"a": 1, "b": 2}) | ||
| self.assertEqual(sorted(obj), ["a", "b"]) | ||
|
|
||
| def test_dict_getitem(self): | ||
| obj = JsonObject({"key": "value"}) | ||
| self.assertEqual(obj["key"], "value") | ||
|
|
||
| def test_null_len(self): | ||
| obj = JsonObject(None) | ||
| self.assertEqual(len(obj), 0) | ||
|
|
||
| def test_null_bool(self): | ||
| obj = JsonObject(None) | ||
| self.assertFalse(obj) | ||
|
|
||
| def test_scalar_len(self): | ||
| obj = JsonObject(42) | ||
| self.assertEqual(len(obj), 1) | ||
|
|
||
| def test_scalar_bool(self): | ||
| obj = JsonObject(42) | ||
| self.assertTrue(obj) | ||
|
|
||
| def test_scalar_not_iterable(self): | ||
| obj = JsonObject(42) | ||
| with self.assertRaises(TypeError): | ||
| iter(obj) | ||
|
|
||
| def test_scalar_not_subscriptable(self): | ||
| obj = JsonObject(42) | ||
| with self.assertRaises(TypeError): | ||
| obj[0] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation of
__eq__for a nullJsonObjectbreaks the symmetry of the equality operator. Specifically,JsonObject(None) == {}evaluates toTrue, while the reverse,{} == JsonObject(None), evaluates toFalse. This can lead to subtle and hard-to-debug issues.Furthermore, from a conceptual standpoint, a JSON
nullvalue is distinct from an empty JSON object ({}). Equating them could lead to incorrect assumptions in consumer code.To ensure symmetry and maintain a clear distinction between
nulland an empty object, I recommend that a nullJsonObjectshould only be equal toNoneor another nullJsonObject.